37 changed files with 5657 additions and 2 deletions
-
6.gitignore
-
57restscrape/uBlock/1p-filters.html
-
69restscrape/uBlock/3p-filters.html
-
47restscrape/uBlock/about.html
-
52restscrape/uBlock/asset-viewer.html
-
45restscrape/uBlock/background.html
-
23restscrape/uBlock/cloud-ui.html
-
36restscrape/uBlock/dashboard.html
-
66restscrape/uBlock/document-blocked.html
-
61restscrape/uBlock/dyna-rules.html
-
238restscrape/uBlock/epicker.html
-
9restscrape/uBlock/is-webrtc-supported.html
-
21restscrape/uBlock/lib/codemirror/LICENSE
-
49restscrape/uBlock/lib/codemirror/README.md
-
127restscrape/uBlock/lib/codemirror/addon/display/panel.js
-
119restscrape/uBlock/lib/codemirror/addon/merge/merge.css
-
1002restscrape/uBlock/lib/codemirror/addon/merge/merge.js
-
122restscrape/uBlock/lib/codemirror/addon/scroll/annotatescrollbar.js
-
8restscrape/uBlock/lib/codemirror/addon/search/matchesonscrollbar.css
-
97restscrape/uBlock/lib/codemirror/addon/search/matchesonscrollbar.js
-
293restscrape/uBlock/lib/codemirror/addon/search/searchcursor.js
-
72restscrape/uBlock/lib/codemirror/addon/selection/active-line.js
-
34restscrape/uBlock/lib/diff/README.md
-
243restscrape/uBlock/lib/diff/swatinem_diff.js
-
52restscrape/uBlock/lib/lz4/README.md
-
171restscrape/uBlock/lib/lz4/lz4-block-codec-any.js
-
297restscrape/uBlock/lib/lz4/lz4-block-codec-js.js
-
194restscrape/uBlock/lib/lz4/lz4-block-codec-wasm.js
-
BINrestscrape/uBlock/lib/lz4/lz4-block-codec.wasm
-
745restscrape/uBlock/lib/lz4/lz4-block-codec.wat
-
328restscrape/uBlock/lib/publicsuffixlist.js
-
530restscrape/uBlock/lib/punycode.js
-
204restscrape/uBlock/logger-ui.html
-
75restscrape/uBlock/popup.html
-
71restscrape/uBlock/settings.html
-
37restscrape/uBlock/shortcuts.html
-
59restscrape/uBlock/whitelist.html
@ -0,0 +1,57 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — Your filters</title> |
|||
|
|||
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css"> |
|||
<link rel="stylesheet" href="lib/codemirror/addon/search/matchesonscrollbar.css"> |
|||
|
|||
<link rel="stylesheet" href="css/common.css"> |
|||
<link rel="stylesheet" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" href="css/cloud-ui.css"> |
|||
<link rel="stylesheet" href="css/1p-filters.css"> |
|||
<link rel="stylesheet" href="css/codemirror.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
<div id="cloudWidget" class="hide" data-cloud-entry="myFiltersPane"></div> |
|||
|
|||
<p class="vverbose"><span data-i18n="1pFormatHint"></span> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Static-filter-syntax" target="_blank"></a></p> |
|||
<p> |
|||
<button id="userFiltersApply" class="custom important iconifiable" type="button" disabled><span class="fa"></span><span data-i18n="1pApplyChanges"></span></button> |
|||
<button id="userFiltersRevert" class="custom iconifiable" type="button" disabled><span class="fa"></span><span data-i18n="genericRevert"></span></button> |
|||
   |
|||
<button id="importUserFiltersFromFile" class="custom iconifiable" type="button"><span class="fa"></span><span data-i18n="1pImport"></span></button> |
|||
<button id="exportUserFiltersToFile" class="custom iconifiable" type="button"><span class="fa"></span><span data-i18n="1pExport"></span></button> |
|||
</p> |
|||
</div> |
|||
<div id="userFilters" class="codeMirrorContainer codeMirrorFillVertical" spellcheck="false"></div> |
|||
<div class="hidden"> |
|||
<input id="importFilePicker" type="file" accept="text/plain"> |
|||
</div> |
|||
|
|||
<script src="lib/codemirror/lib/codemirror.js"></script> |
|||
<script src="lib/codemirror/addon/display/panel.js"></script> |
|||
<script src="lib/codemirror/addon/scroll/annotatescrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/matchesonscrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/searchcursor.js"></script> |
|||
<script src="lib/codemirror/addon/selection/active-line.js"></script> |
|||
|
|||
<script src="js/codemirror/search.js"></script> |
|||
<script src="js/codemirror/ubo-static-filtering.js"></script> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/cloud-ui.js"></script> |
|||
<script src="js/1p-filters.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,69 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — Filter lists</title> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/cloud-ui.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/3p-filters.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
|
|||
<div id="cloudWidget" class="hide" data-cloud-entry="tpFiltersPane"></div> |
|||
<ul id="options" class="root"> |
|||
<li><button id="buttonUpdate" class="custom important disabled" data-i18n="3pUpdateNow"></button> |
|||
<button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button> |
|||
<button id="buttonApply" class="custom important disabled" data-i18n="3pApplyChanges"></button> |
|||
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1" for="autoUpdate"></label>  |
|||
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label><button class="whatisthis"></button> |
|||
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div> |
|||
<li><input type="checkbox" id="ignoreGenericCosmeticFilters"><label data-i18n="3pIgnoreGenericCosmeticFilters" for="ignoreGenericCosmeticFilters"></label><button class="whatisthis"></button> |
|||
<div class="whatisthis-expandable para" data-i18n="3pIgnoreGenericCosmeticFiltersInfo"></div> |
|||
</ul> |
|||
<ul class="root"> |
|||
<li><span id="listsOfBlockedHostsPrompt"></span> |
|||
<ul id="lists"></ul> |
|||
</ul> |
|||
|
|||
</div> |
|||
|
|||
<div id="templates" style="display: none;"> |
|||
<ul> |
|||
<li class="groupEntry"><span class="geDetails"><span class="geName"></span> <span class="geCount dim"></span></span> |
|||
<ul class="listEntries"></ul> |
|||
</li> |
|||
<li class="listEntry"> |
|||
<input type="checkbox"><!-- |
|||
--><a class="content" type="text/plain" target="_blank" href=""></a>​<!-- |
|||
--><a class="fa support" href="" target="_blank"></a>​<!-- |
|||
--><a class="fa remove" href=""></a>​<!-- |
|||
--><a class="fa mustread" href="" target="_blank"></a>​<!-- |
|||
--><span class="fa status unsecure" title="http"></span>​<!-- |
|||
--><span class="counts dim"></span>​<!-- |
|||
--><span class="fa status obsolete" data-i18n-title="3pExternalListObsolete"></span>​<!-- |
|||
--><span class="fa status cache"></span>​<!-- |
|||
--><span class="fa status updating" data-i18n-title="3pUpdating"></span>​<!-- |
|||
--><span class="fa status failed" data-i18n-title="3pNetworkError"></span> |
|||
</li> |
|||
<li class="listEntry toImport"><input type="checkbox" id="importLists"><label for="importLists" data-i18n="3pImport"></label><!-- |
|||
--><a class="fa info towiki" href="https://github.com/gorhill/uBlock/wiki/Filter-lists-from-around-the-web" target="_blank"></a><!-- |
|||
--><textarea id="externalLists" dir="ltr" spellcheck="false" placeholder="3pExternalListsHint"></textarea> |
|||
</ul> |
|||
</div> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/cloud-ui.js"></script> |
|||
<script src="js/3p-filters.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,47 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — About</title> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
<p id="aboutNameVer"></p> |
|||
<p>Copyright (c) Raymond Hill 2014-present<br> |
|||
|
|||
</p> |
|||
<ul> |
|||
<li><a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a> |
|||
<li><a href="https://github.com/gorhill/uBlock/wiki" data-i18n="aboutWiki"></a> |
|||
<li><a href="https://old.reddit.com/r/uBlockOrigin/" data-i18n="aboutSupport"></a> |
|||
<li><a href="https://github.com/uBlockOrigin/uBlock-issues/issues" data-i18n="aboutIssues"></a> |
|||
<li><a href="https://github.com/gorhill/uBlock" data-i18n="aboutCode"></a> |
|||
<li><span data-i18n="aboutContributors"></span> |
|||
<ul> |
|||
<li><a href="https://github.com/gorhill/uBlock/graphs/contributors">GitHub</a> |
|||
<li><a href="https://crowdin.net/project/ublock">Crowdin</a> |
|||
</ul> |
|||
<li><span data-i18n="aboutDependencies"></span><ul> |
|||
<li><a href="https://github.com/bestiejs/punycode.js" target="_blank">Punycode.js</a> by <a href="https://github.com/mathiasbynens">Mathias Bynens</a> |
|||
<li><a href="https://fontawesome.com/" target="_blank">Font Awesome</a> by <a href="https://github.com/davegandy">Dave Gandy</a> |
|||
<li><a href="https://codemirror.net/" target="_blank">CodeMirror</a> by <a href="https://github.com/marijnh">Marijn Haverbeke</a> |
|||
<li><a href="https://github.com/Swatinem/diff" target="_blank">An implementation of Myers' diff algorithm</a> by <a href="https://github.com/Swatinem">Arpad Borsos</a> |
|||
</ul> |
|||
</ul> |
|||
</div> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/about.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,52 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title data-i18n="assetViewerPageName"></title> |
|||
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css"> |
|||
<link rel="stylesheet" href="lib/codemirror/addon/search/matchesonscrollbar.css"> |
|||
<link rel="stylesheet" href="css/common.css"> |
|||
<link rel="stylesheet" href="css/codemirror.css"> |
|||
<link rel="shortcut icon" type="image/png" href="img/icon_32.png"/> |
|||
<style> |
|||
body { |
|||
border: 0; |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
#content { |
|||
height: 100vh; |
|||
width: 100vw; |
|||
} |
|||
|
|||
/* https://github.com/uBlockOrigin/uBlock-issues/issues/292 */ |
|||
.CodeMirror-wrap pre { |
|||
word-break: break-all; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div id="content" class="codeMirrorContainer"></div> |
|||
|
|||
<script src="lib/codemirror/lib/codemirror.js"></script> |
|||
<script src="lib/codemirror/addon/display/panel.js"></script> |
|||
<script src="lib/codemirror/addon/scroll/annotatescrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/matchesonscrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/searchcursor.js"></script> |
|||
<script src="lib/codemirror/addon/selection/active-line.js"></script> |
|||
|
|||
<script src="js/codemirror/search.js"></script> |
|||
<script src="js/codemirror/ubo-static-filtering.js"></script> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/asset-viewer.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,45 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>uBlock Origin</title> |
|||
</head> |
|||
<body> |
|||
<script src="lib/lz4/lz4-block-codec-any.js"></script> |
|||
<script src="lib/punycode.js"></script> |
|||
<script src="lib/publicsuffixlist.js"></script> |
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-background.js"></script> |
|||
<script src="js/vapi-webrequest.js"></script><!-- Forks can pick the webext, chromium, or their own implementation --> |
|||
<script src="js/background.js"></script> |
|||
<script src="js/traffic.js"></script> |
|||
<script src="js/hntrie.js"></script> |
|||
<script src="js/utils.js"></script> |
|||
<script src="js/uritools.js"></script> |
|||
<script src="js/lz4.js"></script> |
|||
<script src="js/cachestorage.js"></script> |
|||
<script src="js/assets.js"></script> |
|||
<script src="js/filtering-context.js"></script> |
|||
<script src="js/redirect-engine.js"></script> |
|||
<script src="js/dynamic-net-filtering.js"></script> |
|||
<script src="js/static-net-filtering.js"></script> |
|||
<script src="js/url-net-filtering.js"></script> |
|||
<script src="js/static-ext-filtering.js"></script> |
|||
<script src="js/cosmetic-filtering.js"></script> |
|||
<script src="js/scriptlet-filtering.js"></script> |
|||
<script src="js/html-filtering.js"></script> |
|||
<script src="js/hnswitches.js"></script> |
|||
<script src="js/ublock.js"></script> |
|||
<script src="js/messaging.js"></script> |
|||
<script src="js/storage.js"></script> |
|||
<script src="js/logger.js"></script> |
|||
<script src="js/pagestore.js"></script> |
|||
<script src="js/tab.js"></script> |
|||
<script src="js/text-encode.js"></script> |
|||
<script src="js/contextmenu.js"></script> |
|||
<script src="js/reverselookup.js"></script> |
|||
<script src="js/start.js"></script> |
|||
<script src="js/commands.js"></script> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,23 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title></title> |
|||
</head> |
|||
<body> |
|||
<div class="cloudTools"> |
|||
<button id="cloudPush" type="button" class="custom" data-i18n-title="cloudPush"><span class="fa"></span></button> |
|||
<span id="cloudInfo" data-i18n="cloudNoData"></span> |
|||
<button id="cloudPull" type="button" class="custom" data-i18n-title="cloudPull" disabled><span class="fa"></span></button> |
|||
<button id="cloudPullAndMerge" type="button" class="custom" data-i18n-title="cloudPullAndMerge" disabled><span class="fa"><span></span></span></button> |
|||
</div> |
|||
<p id="cloudError"></p> |
|||
<span id="cloudCog" class="fa"></span> |
|||
<div id="cloudOptions"> |
|||
<div> |
|||
<p><label data-i18n="cloudDeviceNamePrompt"></label> <input id="cloudDeviceName" type="text" value=""> |
|||
<p><button id="cloudOptionsSubmit" type="button" data-i18n="genericSubmit"></button> |
|||
</div> |
|||
</div> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,36 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title data-i18n="dashboardName"></title> |
|||
<link href="css/dashboard.css" rel="stylesheet" type="text/css"> |
|||
<link href="css/common.css" rel="stylesheet" type="text/css"> |
|||
<link rel="shortcut icon" type="image/png" href="img/icon_16.png"/> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="dashboard-nav"> |
|||
<div id="dashboard-nav-widgets"> |
|||
<span class="hverbose" data-i18n-title="extName"><img src="img/ublock.svg"></span><!-- |
|||
--><a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a><!-- |
|||
--><a class="tabButton" href="#3p-filters.html" data-i18n="3pPageName"></a><!-- |
|||
--><a class="tabButton" href="#1p-filters.html" data-i18n="1pPageName"></a><!-- |
|||
--><a class="tabButton" href="#dyna-rules.html" data-i18n="rulesPageName"></a><!-- |
|||
--><a class="tabButton" href="#whitelist.html" data-i18n="whitelistPageName"></a><!-- |
|||
--><a class="tabButton" href="#shortcuts.html" data-i18n="shortcutsPageName"></a><!-- |
|||
--><a class="tabButton" href="#about.html" data-i18n="aboutPageName"></a> |
|||
</div> |
|||
</div> |
|||
|
|||
<iframe id="iframe" src=""></iframe> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,66 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=yes"> |
|||
<title></title> |
|||
<link rel="stylesheet" href="css/common.css" type="text/css"> |
|||
<link rel="stylesheet" href="css/fa-icons.css" type="text/css"> |
|||
<link rel="stylesheet" type="text/css" href="css/document-blocked.css"> |
|||
</head> |
|||
<body> |
|||
<div id="warningSign"><a class="fa-icon" href="https://github.com/gorhill/uBlock/wiki/Strict-blocking" target="_blank">exclamation-triangle</a></div> |
|||
|
|||
<div> |
|||
<p data-i18n="docblockedPrompt1"></p> |
|||
<div id="theURL" class="collapsed"> |
|||
<p class="code"></p> |
|||
<ul id="parsed"></ul> |
|||
</div> |
|||
</div> |
|||
|
|||
<div> |
|||
<p data-i18n="docblockedPrompt2"></p> |
|||
<p id="why" class="code"></p><!-- |
|||
--><p id="whyex" style="display: none;"><span data-i18n="docblockedFoundIn"></span> <span></span></p> |
|||
</div> |
|||
|
|||
<div> |
|||
<p><button id="back" data-i18n="docblockedBack" type="button"></button> |
|||
<button id="bye" data-i18n="docblockedClose" type="button"></button></p> |
|||
</div> |
|||
|
|||
<div> |
|||
<p id="proceed"></p> |
|||
<p><button id="proceedTemporary" data-i18n="docblockedDisableTemporary" type="button"></button> |
|||
<button id="proceedPermanent" data-i18n="docblockedDisablePermanent" type="button"></button></p> |
|||
</div> |
|||
|
|||
<div id="templates" style="display: none;"> |
|||
<span class="proceed"> |
|||
<span></span> |
|||
<span class="proceedChoice"> |
|||
<select> |
|||
<option class="hn" value="" selected> |
|||
<option class="dn" value=""> |
|||
</select> |
|||
</span> |
|||
<span class="proceedChoice code hn"></span> |
|||
<span></span> |
|||
</span> |
|||
<span class="filterList"> |
|||
<span class="filterListSeparator">•</span> |
|||
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a> <!-- |
|||
--><a class="fa filterListSupport" href="" target="_blank"></a> |
|||
</span> |
|||
</div> |
|||
|
|||
<script src="js/fa-icons.js"></script> |
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/document-blocked.js"></script> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,61 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — Dynamic filtering rules</title> |
|||
<link rel="stylesheet" type="text/css" href="lib/codemirror/lib/codemirror.css"> |
|||
<link rel="stylesheet" type="text/css" href="lib/codemirror/addon/merge/merge.css"> |
|||
|
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/cloud-ui.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dyna-rules.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/codemirror.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
<div id="cloudWidget" class="hide" data-cloud-entry="myRulesPane"></div> |
|||
<p class="vverbose"><span data-i18n="rulesHint"></span> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Dynamic-filtering:-rule-syntax" target="_blank"></a></p> |
|||
<div id="diff"> |
|||
<div class="tools"> |
|||
<div class="ruleActions"> |
|||
<h3 data-i18n="rulesPermanentHeader"></h3> |
|||
<button type="button" class="custom iconifiable" id="exportButton"><span class="fa"></span><span data-i18n="rulesExport"></span></button> |
|||
<button type="button" class="custom iconifiable" id="revertButton"><span class="fa"></span><span data-i18n="rulesRevert"></span></button> |
|||
</div> |
|||
<div class="ruleActions"> |
|||
<h3 data-i18n="rulesTemporaryHeader"></h3> |
|||
<button type="button" class="custom iconifiable" id="commitButton"><span class="fa"></span><span data-i18n="rulesCommit"></span></button> |
|||
<button type="button" class="custom iconifiable" id="importButton"><span class="fa"></span><span data-i18n="rulesImport"></span></button> |
|||
<button type="button" class="custom iconifiable important disabled" id="editSaveButton"><span class="fa"></span><span data-i18n="rulesEditSave"></span></button> |
|||
</div> |
|||
<div id="ruleFilter"><span class="fa"></span> <input type="text" size="20"></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="codeMirrorContainer codeMirrorMergeContainer codeMirrorFillVertical"></div> |
|||
|
|||
<div id="templates" style="display: none;"> |
|||
<input class="hidden" id="importFilePicker" type="file" accept="text/plain"> |
|||
<span class="hidden" data-i18n="rulesDefaultFileName"></span> |
|||
</div> |
|||
|
|||
<script src="lib/diff/swatinem_diff.js"></script> |
|||
<script src="lib/codemirror/lib/codemirror.js"></script> |
|||
<script src="lib/codemirror/addon/merge/merge.js"></script> |
|||
<script src="lib/codemirror/addon/selection/active-line.js"></script> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/cloud-ui.js"></script> |
|||
<script src="js/dyna-rules.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,238 @@ |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>uBlock Origin Element Picker</title> |
|||
<style> |
|||
html#ublock0-epicker, |
|||
#ublock0-epicker body { |
|||
background: transparent !important; |
|||
color: black !important; |
|||
font: 12px sans-serif !important; |
|||
height: 100% !important; |
|||
margin: 0 !important; |
|||
overflow: hidden !important; |
|||
width: 100% !important; |
|||
} |
|||
#ublock0-epicker :focus { |
|||
outline: none !important; |
|||
} |
|||
#ublock0-epicker ul, |
|||
#ublock0-epicker li, |
|||
#ublock0-epicker div { |
|||
display: block !important; |
|||
} |
|||
#ublock0-epicker ul { |
|||
margin: 0.25em 0 0 0 !important; |
|||
} |
|||
#ublock0-epicker button { |
|||
background-color: #ccc !important; |
|||
border: 1px solid #aaa !important; |
|||
border-radius: 3px !important; |
|||
box-sizing: border-box !important; |
|||
box-shadow: none !important; |
|||
color: #000 !important; |
|||
cursor: pointer !important; |
|||
margin: 0 0 0 2px !important; |
|||
opacity: 0.7 !important; |
|||
padding: 4px 6px !important; |
|||
} |
|||
#ublock0-epicker button:first-of-type { |
|||
margin-left: 0 !important; |
|||
} |
|||
#ublock0-epicker button:disabled { |
|||
color: #999 !important; |
|||
background-color: #ccc !important; |
|||
} |
|||
#ublock0-epicker button:not(:disabled):hover { |
|||
opacity: 1 !important; |
|||
} |
|||
#ublock0-epicker #create:not(:disabled) { |
|||
background-color: hsl(36, 100%, 83%) !important; |
|||
border-color: hsl(36, 50%, 60%) !important; |
|||
} |
|||
#ublock0-epicker #preview { |
|||
float: left !important; |
|||
} |
|||
#ublock0-epicker body.preview #preview { |
|||
background-color: hsl(204, 100%, 83%) !important; |
|||
border-color: hsl(204, 50%, 60%) !important; |
|||
} |
|||
#ublock0-epicker section { |
|||
border: 0 !important; |
|||
box-sizing: border-box !important; |
|||
display: inline-block !important; |
|||
width: 100% !important; |
|||
} |
|||
#ublock0-epicker section > div:first-child { |
|||
border: 1px solid #aaa !important; |
|||
margin: 0 !important; |
|||
position: relative !important; |
|||
} |
|||
#ublock0-epicker section.invalidFilter > div:first-child { |
|||
border-color: red !important; |
|||
} |
|||
#ublock0-epicker section > div:first-child > textarea { |
|||
background-color: #fff !important; |
|||
border: none !important; |
|||
box-sizing: border-box !important; |
|||
color: #000 !important; |
|||
font: 11px monospace !important; |
|||
height: 8em !important; |
|||
margin: 0 !important; |
|||
overflow: hidden !important; |
|||
overflow-y: auto !important; |
|||
padding: 2px !important; |
|||
resize: none !important; |
|||
width: 100% !important; |
|||
word-break: break-all !important; |
|||
} |
|||
#ublock0-epicker #resultsetCount { |
|||
background-color: #aaa !important; |
|||
bottom: 0 !important; |
|||
color: white !important; |
|||
padding: 2px 4px !important; |
|||
position: absolute !important; |
|||
right: 0 !important; |
|||
} |
|||
#ublock0-epicker section.invalidFilter #resultsetCount { |
|||
background-color: red !important; |
|||
} |
|||
#ublock0-epicker section > div:first-child + div { |
|||
direction: ltr !important; |
|||
margin: 2px 0 !important; |
|||
text-align: right !important; |
|||
} |
|||
#ublock0-epicker ul { |
|||
padding: 0 !important; |
|||
list-style-type: none !important; |
|||
text-align: left !important; |
|||
overflow: hidden !important; |
|||
} |
|||
#ublock0-epicker aside > ul { |
|||
max-height: 16em !important; |
|||
overflow-y: auto !important; |
|||
} |
|||
#ublock0-epicker aside > ul > li:first-of-type { |
|||
margin-bottom: 0.5em !important; |
|||
} |
|||
#ublock0-epicker ul > li > span:nth-of-type(1) { |
|||
font-weight: bold !important; |
|||
} |
|||
#ublock0-epicker ul > li > span:nth-of-type(2) { |
|||
font-size: smaller !important; |
|||
color: gray !important; |
|||
} |
|||
#ublock0-epicker ul > li > ul { |
|||
list-style-type: none !important; |
|||
margin: 0 0 0 1em !important; |
|||
overflow: hidden !important; |
|||
text-align: left !important; |
|||
} |
|||
#ublock0-epicker ul > li > ul > li { |
|||
font: 11px monospace !important; |
|||
white-space: nowrap !important; |
|||
cursor: pointer !important; |
|||
direction: ltr !important; |
|||
} |
|||
#ublock0-epicker ul > li > ul > li:hover { |
|||
background-color: white !important; |
|||
} |
|||
#ublock0-epicker svg { |
|||
position: fixed !important; |
|||
top: 0 !important; |
|||
left: 0 !important; |
|||
cursor: crosshair !important; |
|||
width: 100% !important; |
|||
height: 100% !important; |
|||
} |
|||
#ublock0-epicker .paused > svg { |
|||
cursor: not-allowed !important; |
|||
} |
|||
#ublock0-epicker svg > path:first-child { |
|||
fill: rgba(0,0,0,0.5) !important; |
|||
fill-rule: evenodd !important; |
|||
} |
|||
#ublock0-epicker svg > path + path { |
|||
stroke: #F00 !important; |
|||
stroke-width: 0.5px !important; |
|||
fill: rgba(255,63,63,0.20) !important; |
|||
} |
|||
#ublock0-epicker body.zap svg > path + path { |
|||
stroke: #FF0 !important; |
|||
stroke-width: 0.5px !important; |
|||
fill: rgba(255,255,63,0.20) !important; |
|||
} |
|||
#ublock0-epicker body.preview svg > path { |
|||
fill: rgba(0,0,0,0.10) !important; |
|||
} |
|||
#ublock0-epicker body.preview svg > path + path { |
|||
stroke: none !important; |
|||
} |
|||
#ublock0-epicker aside { |
|||
background-color: #eee !important; |
|||
border: 1px solid #aaa !important; |
|||
bottom: 4px !important; |
|||
box-sizing: border-box !important; |
|||
min-width: 24em !important; |
|||
padding: 4px !important; |
|||
position: fixed !important; |
|||
right: 4px !important; |
|||
visibility: hidden !important; |
|||
width: calc(40% - 4px) !important; |
|||
} |
|||
#ublock0-epicker body.paused > aside { |
|||
opacity: 0.1; |
|||
visibility: visible !important; |
|||
z-index: 100 !important; |
|||
} |
|||
/** |
|||
https://github.com/gorhill/uBlock/issues/3449 |
|||
https://github.com/uBlockOrigin/uBlock-issues/issues/55 |
|||
**/ |
|||
@keyframes startDialog { |
|||
0% { opacity: 1.0; } |
|||
60% { opacity: 1.0; } |
|||
100% { opacity: 0.1; } |
|||
} |
|||
#ublock0-epicker body.paused > aside:not(:hover):not(.show) { |
|||
animation-duration: 1.6s !important; |
|||
animation-name: startDialog !important; |
|||
animation-timing-function: linear !important; |
|||
} |
|||
#ublock0-epicker body.paused > aside:hover { |
|||
opacity: 1 !important; |
|||
} |
|||
#ublock0-epicker body.paused > aside.show { |
|||
opacity: 1 !important; |
|||
} |
|||
#ublock0-epicker body.paused > aside.hide { |
|||
opacity: 0.1 !important; |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body direction="{{bidi_dir}}"> |
|||
<svg><path d></path><path d></path></svg> |
|||
<aside> |
|||
<section> |
|||
<div> |
|||
<textarea lang="en" dir="ltr" spellcheck="false"></textarea> |
|||
<div id="resultsetCount"></div> |
|||
</div> |
|||
<div><!-- |
|||
--><button id="preview" type="button">{{preview}}</button><!-- |
|||
--><button id="create" type="button" disabled>{{create}}</button><!-- |
|||
--><button id="pick" type="button">{{pick}}</button><!-- |
|||
--><button id="quit" type="button">{{quit}}</button><!-- |
|||
--></div> |
|||
</section> |
|||
<ul> |
|||
<li id="netFilters"> |
|||
<span>{{netFilters}}</span><ul lang="en" class="changeFilter"></ul> |
|||
</li> |
|||
<li id="cosmeticFilters"> |
|||
<span>{{cosmeticFilters}}</span> <span>{{cosmeticFiltersHint}}</span> |
|||
<ul lang="en" class="changeFilter"></ul> |
|||
</li> |
|||
</ul> |
|||
</aside> |
|||
</body> |
|||
@ -0,0 +1,9 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title></title> |
|||
<script async src="js/is-webrtc-supported.js"></script> |
|||
</head> |
|||
<body></body> |
|||
</html> |
|||
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
|||
@ -0,0 +1,49 @@ |
|||
# CodeMirror |
|||
|
|||
[](https://travis-ci.org/codemirror/CodeMirror) |
|||
[](https://www.npmjs.org/package/codemirror) |
|||
[](https://gitter.im/codemirror/CodeMirror) |
|||
[Funding status: ](https://marijnhaverbeke.nl/fund/) |
|||
|
|||
CodeMirror is a versatile text editor implemented in JavaScript for |
|||
the browser. It is specialized for editing code, and comes with over |
|||
100 language modes and various addons that implement more advanced |
|||
editing functionality. Every language comes with fully-featured code |
|||
and syntax highlighting to help with reading and editing complex code. |
|||
|
|||
A rich programming API and a CSS theming system are available for |
|||
customizing CodeMirror to fit your application, and extending it with |
|||
new functionality. |
|||
|
|||
You can find more information (and the |
|||
[manual](https://codemirror.net/doc/manual.html)) on the [project |
|||
page](https://codemirror.net). For questions and discussion, use the |
|||
[discussion forum](https://discuss.codemirror.net/). |
|||
|
|||
See |
|||
[CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md) |
|||
for contributing guidelines. |
|||
|
|||
The CodeMirror community aims to be welcoming to everybody. We use the |
|||
[Contributor Covenant |
|||
(1.1)](http://contributor-covenant.org/version/1/1/0/) as our code of |
|||
conduct. |
|||
|
|||
### Installation |
|||
|
|||
Either get the [zip file](https://codemirror.net/codemirror.zip) with |
|||
the latest version, or make sure you have [Node](https://nodejs.org/) |
|||
installed and run: |
|||
|
|||
npm install codemirror |
|||
|
|||
**NOTE**: This is the source repository for the library, and not the |
|||
distribution channel. Cloning it is not the recommended way to install |
|||
the library, and will in fact not work unless you also run the build |
|||
step. |
|||
|
|||
### Quickstart |
|||
|
|||
To build the project, make sure you have Node.js installed (at least version 6) |
|||
and then `npm install`. To run, just open `index.html` in your |
|||
browser (you don't need to run a webserver). Run the tests with `npm test`. |
|||
@ -0,0 +1,127 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
CodeMirror.defineExtension("addPanel", function(node, options) { |
|||
options = options || {}; |
|||
|
|||
if (!this.state.panels) initPanels(this); |
|||
|
|||
var info = this.state.panels; |
|||
var wrapper = info.wrapper; |
|||
var cmWrapper = this.getWrapperElement(); |
|||
var replace = options.replace instanceof Panel && !options.replace.cleared; |
|||
|
|||
if (options.after instanceof Panel && !options.after.cleared) { |
|||
wrapper.insertBefore(node, options.before.node.nextSibling); |
|||
} else if (options.before instanceof Panel && !options.before.cleared) { |
|||
wrapper.insertBefore(node, options.before.node); |
|||
} else if (replace) { |
|||
wrapper.insertBefore(node, options.replace.node); |
|||
info.panels++; |
|||
options.replace.clear(); |
|||
} else if (options.position == "bottom") { |
|||
wrapper.appendChild(node); |
|||
} else if (options.position == "before-bottom") { |
|||
wrapper.insertBefore(node, cmWrapper.nextSibling); |
|||
} else if (options.position == "after-top") { |
|||
wrapper.insertBefore(node, cmWrapper); |
|||
} else { |
|||
wrapper.insertBefore(node, wrapper.firstChild); |
|||
} |
|||
|
|||
var height = (options && options.height) || node.offsetHeight; |
|||
this._setSize(null, info.heightLeft -= height); |
|||
if (!replace) { |
|||
info.panels++; |
|||
} |
|||
if (options.stable && isAtTop(this, node)) |
|||
this.scrollTo(null, this.getScrollInfo().top + height) |
|||
|
|||
return new Panel(this, node, options, height); |
|||
}); |
|||
|
|||
function Panel(cm, node, options, height) { |
|||
this.cm = cm; |
|||
this.node = node; |
|||
this.options = options; |
|||
this.height = height; |
|||
this.cleared = false; |
|||
} |
|||
|
|||
Panel.prototype.clear = function() { |
|||
if (this.cleared) return; |
|||
this.cleared = true; |
|||
var info = this.cm.state.panels; |
|||
this.cm._setSize(null, info.heightLeft += this.height); |
|||
if (this.options.stable && isAtTop(this.cm, this.node)) |
|||
this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height) |
|||
info.wrapper.removeChild(this.node); |
|||
if (--info.panels == 0) removePanels(this.cm); |
|||
}; |
|||
|
|||
Panel.prototype.changed = function(height) { |
|||
var newHeight = height == null ? this.node.offsetHeight : height; |
|||
var info = this.cm.state.panels; |
|||
this.cm._setSize(null, info.heightLeft -= (newHeight - this.height)); |
|||
this.height = newHeight; |
|||
}; |
|||
|
|||
function initPanels(cm) { |
|||
var wrap = cm.getWrapperElement(); |
|||
var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle; |
|||
var height = parseInt(style.height); |
|||
var info = cm.state.panels = { |
|||
setHeight: wrap.style.height, |
|||
heightLeft: height, |
|||
panels: 0, |
|||
wrapper: document.createElement("div") |
|||
}; |
|||
wrap.parentNode.insertBefore(info.wrapper, wrap); |
|||
var hasFocus = cm.hasFocus(); |
|||
info.wrapper.appendChild(wrap); |
|||
if (hasFocus) cm.focus(); |
|||
|
|||
cm._setSize = cm.setSize; |
|||
if (height != null) cm.setSize = function(width, newHeight) { |
|||
if (newHeight == null) return this._setSize(width, newHeight); |
|||
info.setHeight = newHeight; |
|||
if (typeof newHeight != "number") { |
|||
var px = /^(\d+\.?\d*)px$/.exec(newHeight); |
|||
if (px) { |
|||
newHeight = Number(px[1]); |
|||
} else { |
|||
info.wrapper.style.height = newHeight; |
|||
newHeight = info.wrapper.offsetHeight; |
|||
info.wrapper.style.height = ""; |
|||
} |
|||
} |
|||
cm._setSize(width, info.heightLeft += (newHeight - height)); |
|||
height = newHeight; |
|||
}; |
|||
} |
|||
|
|||
function removePanels(cm) { |
|||
var info = cm.state.panels; |
|||
cm.state.panels = null; |
|||
|
|||
var wrap = cm.getWrapperElement(); |
|||
info.wrapper.parentNode.replaceChild(wrap, info.wrapper); |
|||
wrap.style.height = info.setHeight; |
|||
cm.setSize = cm._setSize; |
|||
cm.setSize(); |
|||
} |
|||
|
|||
function isAtTop(cm, dom) { |
|||
for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling) |
|||
if (sibling == cm.getWrapperElement()) return true |
|||
return false |
|||
} |
|||
}); |
|||
@ -0,0 +1,119 @@ |
|||
.CodeMirror-merge { |
|||
position: relative; |
|||
border: 1px solid #ddd; |
|||
white-space: pre; |
|||
} |
|||
|
|||
.CodeMirror-merge, .CodeMirror-merge .CodeMirror { |
|||
height: 350px; |
|||
} |
|||
|
|||
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; } |
|||
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; } |
|||
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; } |
|||
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; } |
|||
|
|||
.CodeMirror-merge-pane { |
|||
display: inline-block; |
|||
white-space: normal; |
|||
vertical-align: top; |
|||
} |
|||
.CodeMirror-merge-pane-rightmost { |
|||
position: absolute; |
|||
right: 0px; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.CodeMirror-merge-gap { |
|||
z-index: 2; |
|||
display: inline-block; |
|||
height: 100%; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
overflow: hidden; |
|||
border-left: 1px solid #ddd; |
|||
border-right: 1px solid #ddd; |
|||
position: relative; |
|||
background: #f8f8f8; |
|||
} |
|||
|
|||
.CodeMirror-merge-scrolllock-wrap { |
|||
position: absolute; |
|||
bottom: 0; left: 50%; |
|||
} |
|||
.CodeMirror-merge-scrolllock { |
|||
position: relative; |
|||
left: -50%; |
|||
cursor: pointer; |
|||
color: #555; |
|||
line-height: 1; |
|||
} |
|||
.CodeMirror-merge-scrolllock:after { |
|||
content: "\21db\00a0\00a0\21da"; |
|||
} |
|||
.CodeMirror-merge-scrolllock.CodeMirror-merge-scrolllock-enabled:after { |
|||
content: "\21db\21da"; |
|||
} |
|||
|
|||
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right { |
|||
position: absolute; |
|||
left: 0; top: 0; |
|||
right: 0; bottom: 0; |
|||
line-height: 1; |
|||
} |
|||
|
|||
.CodeMirror-merge-copy { |
|||
position: absolute; |
|||
cursor: pointer; |
|||
color: #44c; |
|||
z-index: 3; |
|||
} |
|||
|
|||
.CodeMirror-merge-copy-reverse { |
|||
position: absolute; |
|||
cursor: pointer; |
|||
color: #44c; |
|||
} |
|||
|
|||
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; } |
|||
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; } |
|||
|
|||
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==); |
|||
background-position: bottom left; |
|||
background-repeat: repeat-x; |
|||
} |
|||
|
|||
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==); |
|||
background-position: bottom left; |
|||
background-repeat: repeat-x; |
|||
} |
|||
|
|||
.CodeMirror-merge-r-chunk { background: #ffffe0; } |
|||
.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; } |
|||
.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; } |
|||
.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; } |
|||
|
|||
.CodeMirror-merge-l-chunk { background: #eef; } |
|||
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; } |
|||
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; } |
|||
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; } |
|||
|
|||
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; } |
|||
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; } |
|||
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; } |
|||
|
|||
.CodeMirror-merge-collapsed-widget:before { |
|||
content: "(...)"; |
|||
} |
|||
.CodeMirror-merge-collapsed-widget { |
|||
cursor: pointer; |
|||
color: #88b; |
|||
background: #eef; |
|||
border: 1px solid #ddf; |
|||
font-size: 90%; |
|||
padding: 0 3px; |
|||
border-radius: 4px; |
|||
} |
|||
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; } |
|||
1002
restscrape/uBlock/lib/codemirror/addon/merge/merge.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,122 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineExtension("annotateScrollbar", function(options) { |
|||
if (typeof options == "string") options = {className: options}; |
|||
return new Annotation(this, options); |
|||
}); |
|||
|
|||
CodeMirror.defineOption("scrollButtonHeight", 0); |
|||
|
|||
function Annotation(cm, options) { |
|||
this.cm = cm; |
|||
this.options = options; |
|||
this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight"); |
|||
this.annotations = []; |
|||
this.doRedraw = this.doUpdate = null; |
|||
this.div = cm.getWrapperElement().appendChild(document.createElement("div")); |
|||
this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none"; |
|||
this.computeScale(); |
|||
|
|||
function scheduleRedraw(delay) { |
|||
clearTimeout(self.doRedraw); |
|||
self.doRedraw = setTimeout(function() { self.redraw(); }, delay); |
|||
} |
|||
|
|||
var self = this; |
|||
cm.on("refresh", this.resizeHandler = function() { |
|||
clearTimeout(self.doUpdate); |
|||
self.doUpdate = setTimeout(function() { |
|||
if (self.computeScale()) scheduleRedraw(20); |
|||
}, 100); |
|||
}); |
|||
cm.on("markerAdded", this.resizeHandler); |
|||
cm.on("markerCleared", this.resizeHandler); |
|||
if (options.listenForChanges !== false) |
|||
cm.on("change", this.changeHandler = function() { |
|||
scheduleRedraw(250); |
|||
}); |
|||
} |
|||
|
|||
Annotation.prototype.computeScale = function() { |
|||
var cm = this.cm; |
|||
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) / |
|||
cm.getScrollerElement().scrollHeight |
|||
if (hScale != this.hScale) { |
|||
this.hScale = hScale; |
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
Annotation.prototype.update = function(annotations) { |
|||
this.annotations = annotations; |
|||
this.redraw(); |
|||
}; |
|||
|
|||
Annotation.prototype.redraw = function(compute) { |
|||
if (compute !== false) this.computeScale(); |
|||
var cm = this.cm, hScale = this.hScale; |
|||
|
|||
var frag = document.createDocumentFragment(), anns = this.annotations; |
|||
|
|||
var wrapping = cm.getOption("lineWrapping"); |
|||
var singleLineH = wrapping && cm.defaultTextHeight() * 1.5; |
|||
var curLine = null, curLineObj = null; |
|||
function getY(pos, top) { |
|||
if (curLine != pos.line) { |
|||
curLine = pos.line; |
|||
curLineObj = cm.getLineHandle(curLine); |
|||
} |
|||
if ((curLineObj.widgets && curLineObj.widgets.length) || |
|||
(wrapping && curLineObj.height > singleLineH)) |
|||
return cm.charCoords(pos, "local")[top ? "top" : "bottom"]; |
|||
var topY = cm.heightAtLine(curLineObj, "local"); |
|||
return topY + (top ? 0 : curLineObj.height); |
|||
} |
|||
|
|||
var lastLine = cm.lastLine() |
|||
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) { |
|||
var ann = anns[i]; |
|||
if (ann.to.line > lastLine) continue; |
|||
var top = nextTop || getY(ann.from, true) * hScale; |
|||
var bottom = getY(ann.to, false) * hScale; |
|||
while (i < anns.length - 1) { |
|||
if (anns[i + 1].to.line > lastLine) break; |
|||
nextTop = getY(anns[i + 1].from, true) * hScale; |
|||
if (nextTop > bottom + .9) break; |
|||
ann = anns[++i]; |
|||
bottom = getY(ann.to, false) * hScale; |
|||
} |
|||
if (bottom == top) continue; |
|||
var height = Math.max(bottom - top, 3); |
|||
|
|||
var elt = frag.appendChild(document.createElement("div")); |
|||
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: " |
|||
+ (top + this.buttonHeight) + "px; height: " + height + "px"; |
|||
elt.className = this.options.className; |
|||
if (ann.id) { |
|||
elt.setAttribute("annotation-id", ann.id); |
|||
} |
|||
} |
|||
this.div.textContent = ""; |
|||
this.div.appendChild(frag); |
|||
}; |
|||
|
|||
Annotation.prototype.clear = function() { |
|||
this.cm.off("refresh", this.resizeHandler); |
|||
this.cm.off("markerAdded", this.resizeHandler); |
|||
this.cm.off("markerCleared", this.resizeHandler); |
|||
if (this.changeHandler) this.cm.off("change", this.changeHandler); |
|||
this.div.parentNode.removeChild(this.div); |
|||
}; |
|||
}); |
|||
@ -0,0 +1,8 @@ |
|||
.CodeMirror-search-match { |
|||
background: gold; |
|||
border-top: 1px solid orange; |
|||
border-bottom: 1px solid orange; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
opacity: .5; |
|||
} |
|||
@ -0,0 +1,97 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) { |
|||
if (typeof options == "string") options = {className: options}; |
|||
if (!options) options = {}; |
|||
return new SearchAnnotation(this, query, caseFold, options); |
|||
}); |
|||
|
|||
function SearchAnnotation(cm, query, caseFold, options) { |
|||
this.cm = cm; |
|||
this.options = options; |
|||
var annotateOptions = {listenForChanges: false}; |
|||
for (var prop in options) annotateOptions[prop] = options[prop]; |
|||
if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match"; |
|||
this.annotation = cm.annotateScrollbar(annotateOptions); |
|||
this.query = query; |
|||
this.caseFold = caseFold; |
|||
this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1}; |
|||
this.matches = []; |
|||
this.update = null; |
|||
|
|||
this.findMatches(); |
|||
this.annotation.update(this.matches); |
|||
|
|||
var self = this; |
|||
cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); }); |
|||
} |
|||
|
|||
var MAX_MATCHES = 1000; |
|||
|
|||
SearchAnnotation.prototype.findMatches = function() { |
|||
if (!this.gap) return; |
|||
for (var i = 0; i < this.matches.length; i++) { |
|||
var match = this.matches[i]; |
|||
if (match.from.line >= this.gap.to) break; |
|||
if (match.to.line >= this.gap.from) this.matches.splice(i--, 1); |
|||
} |
|||
var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold); |
|||
var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES; |
|||
while (cursor.findNext()) { |
|||
var match = {from: cursor.from(), to: cursor.to()}; |
|||
if (match.from.line >= this.gap.to) break; |
|||
this.matches.splice(i++, 0, match); |
|||
if (this.matches.length > maxMatches) break; |
|||
} |
|||
this.gap = null; |
|||
}; |
|||
|
|||
function offsetLine(line, changeStart, sizeChange) { |
|||
if (line <= changeStart) return line; |
|||
return Math.max(changeStart, line + sizeChange); |
|||
} |
|||
|
|||
SearchAnnotation.prototype.onChange = function(change) { |
|||
var startLine = change.from.line; |
|||
var endLine = CodeMirror.changeEnd(change).line; |
|||
var sizeChange = endLine - change.to.line; |
|||
if (this.gap) { |
|||
this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line); |
|||
this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line); |
|||
} else { |
|||
this.gap = {from: change.from.line, to: endLine + 1}; |
|||
} |
|||
|
|||
if (sizeChange) for (var i = 0; i < this.matches.length; i++) { |
|||
var match = this.matches[i]; |
|||
var newFrom = offsetLine(match.from.line, startLine, sizeChange); |
|||
if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch); |
|||
var newTo = offsetLine(match.to.line, startLine, sizeChange); |
|||
if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch); |
|||
} |
|||
clearTimeout(this.update); |
|||
var self = this; |
|||
this.update = setTimeout(function() { self.updateAfterChange(); }, 250); |
|||
}; |
|||
|
|||
SearchAnnotation.prototype.updateAfterChange = function() { |
|||
this.findMatches(); |
|||
this.annotation.update(this.matches); |
|||
}; |
|||
|
|||
SearchAnnotation.prototype.clear = function() { |
|||
this.cm.off("change", this.changeHandler); |
|||
this.annotation.clear(); |
|||
}; |
|||
}); |
|||
@ -0,0 +1,293 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")) |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod) |
|||
else // Plain browser env
|
|||
mod(CodeMirror) |
|||
})(function(CodeMirror) { |
|||
"use strict" |
|||
var Pos = CodeMirror.Pos |
|||
|
|||
function regexpFlags(regexp) { |
|||
var flags = regexp.flags |
|||
return flags != null ? flags : (regexp.ignoreCase ? "i" : "") |
|||
+ (regexp.global ? "g" : "") |
|||
+ (regexp.multiline ? "m" : "") |
|||
} |
|||
|
|||
function ensureFlags(regexp, flags) { |
|||
var current = regexpFlags(regexp), target = current |
|||
for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1) |
|||
target += flags.charAt(i) |
|||
return current == target ? regexp : new RegExp(regexp.source, target) |
|||
} |
|||
|
|||
function maybeMultiline(regexp) { |
|||
return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source) |
|||
} |
|||
|
|||
function searchRegexpForward(doc, regexp, start) { |
|||
regexp = ensureFlags(regexp, "g") |
|||
for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) { |
|||
regexp.lastIndex = ch |
|||
var string = doc.getLine(line), match = regexp.exec(string) |
|||
if (match) |
|||
return {from: Pos(line, match.index), |
|||
to: Pos(line, match.index + match[0].length), |
|||
match: match} |
|||
} |
|||
} |
|||
|
|||
function searchRegexpForwardMultiline(doc, regexp, start) { |
|||
if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start) |
|||
|
|||
regexp = ensureFlags(regexp, "gm") |
|||
var string, chunk = 1 |
|||
for (var line = start.line, last = doc.lastLine(); line <= last;) { |
|||
// This grows the search buffer in exponentially-sized chunks
|
|||
// between matches, so that nearby matches are fast and don't
|
|||
// require concatenating the whole document (in case we're
|
|||
// searching for something that has tons of matches), but at the
|
|||
// same time, the amount of retries is limited.
|
|||
for (var i = 0; i < chunk; i++) { |
|||
if (line > last) break |
|||
var curLine = doc.getLine(line++) |
|||
string = string == null ? curLine : string + "\n" + curLine |
|||
} |
|||
chunk = chunk * 2 |
|||
regexp.lastIndex = start.ch |
|||
var match = regexp.exec(string) |
|||
if (match) { |
|||
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") |
|||
var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length |
|||
return {from: Pos(startLine, startCh), |
|||
to: Pos(startLine + inside.length - 1, |
|||
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), |
|||
match: match} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function lastMatchIn(string, regexp) { |
|||
var cutOff = 0, match |
|||
for (;;) { |
|||
regexp.lastIndex = cutOff |
|||
var newMatch = regexp.exec(string) |
|||
if (!newMatch) return match |
|||
match = newMatch |
|||
cutOff = match.index + (match[0].length || 1) |
|||
if (cutOff == string.length) return match |
|||
} |
|||
} |
|||
|
|||
function searchRegexpBackward(doc, regexp, start) { |
|||
regexp = ensureFlags(regexp, "g") |
|||
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) { |
|||
var string = doc.getLine(line) |
|||
if (ch > -1) string = string.slice(0, ch) |
|||
var match = lastMatchIn(string, regexp) |
|||
if (match) |
|||
return {from: Pos(line, match.index), |
|||
to: Pos(line, match.index + match[0].length), |
|||
match: match} |
|||
} |
|||
} |
|||
|
|||
function searchRegexpBackwardMultiline(doc, regexp, start) { |
|||
regexp = ensureFlags(regexp, "gm") |
|||
var string, chunk = 1 |
|||
for (var line = start.line, first = doc.firstLine(); line >= first;) { |
|||
for (var i = 0; i < chunk; i++) { |
|||
var curLine = doc.getLine(line--) |
|||
string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string |
|||
} |
|||
chunk *= 2 |
|||
|
|||
var match = lastMatchIn(string, regexp) |
|||
if (match) { |
|||
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") |
|||
var startLine = line + before.length, startCh = before[before.length - 1].length |
|||
return {from: Pos(startLine, startCh), |
|||
to: Pos(startLine + inside.length - 1, |
|||
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), |
|||
match: match} |
|||
} |
|||
} |
|||
} |
|||
|
|||
var doFold, noFold |
|||
if (String.prototype.normalize) { |
|||
doFold = function(str) { return str.normalize("NFD").toLowerCase() } |
|||
noFold = function(str) { return str.normalize("NFD") } |
|||
} else { |
|||
doFold = function(str) { return str.toLowerCase() } |
|||
noFold = function(str) { return str } |
|||
} |
|||
|
|||
// Maps a position in a case-folded line back to a position in the original line
|
|||
// (compensating for codepoints increasing in number during folding)
|
|||
function adjustPos(orig, folded, pos, foldFunc) { |
|||
if (orig.length == folded.length) return pos |
|||
for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) { |
|||
if (min == max) return min |
|||
var mid = (min + max) >> 1 |
|||
var len = foldFunc(orig.slice(0, mid)).length |
|||
if (len == pos) return mid |
|||
else if (len > pos) max = mid |
|||
else min = mid + 1 |
|||
} |
|||
} |
|||
|
|||
function searchStringForward(doc, query, start, caseFold) { |
|||
// Empty string would match anything and never progress, so we
|
|||
// define it to match nothing instead.
|
|||
if (!query.length) return null |
|||
var fold = caseFold ? doFold : noFold |
|||
var lines = fold(query).split(/\r|\n\r?/) |
|||
|
|||
search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) { |
|||
var orig = doc.getLine(line).slice(ch), string = fold(orig) |
|||
if (lines.length == 1) { |
|||
var found = string.indexOf(lines[0]) |
|||
if (found == -1) continue search |
|||
var start = adjustPos(orig, string, found, fold) + ch |
|||
return {from: Pos(line, adjustPos(orig, string, found, fold) + ch), |
|||
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)} |
|||
} else { |
|||
var cutFrom = string.length - lines[0].length |
|||
if (string.slice(cutFrom) != lines[0]) continue search |
|||
for (var i = 1; i < lines.length - 1; i++) |
|||
if (fold(doc.getLine(line + i)) != lines[i]) continue search |
|||
var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1] |
|||
if (endString.slice(0, lastLine.length) != lastLine) continue search |
|||
return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch), |
|||
to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function searchStringBackward(doc, query, start, caseFold) { |
|||
if (!query.length) return null |
|||
var fold = caseFold ? doFold : noFold |
|||
var lines = fold(query).split(/\r|\n\r?/) |
|||
|
|||
search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) { |
|||
var orig = doc.getLine(line) |
|||
if (ch > -1) orig = orig.slice(0, ch) |
|||
var string = fold(orig) |
|||
if (lines.length == 1) { |
|||
var found = string.lastIndexOf(lines[0]) |
|||
if (found == -1) continue search |
|||
return {from: Pos(line, adjustPos(orig, string, found, fold)), |
|||
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))} |
|||
} else { |
|||
var lastLine = lines[lines.length - 1] |
|||
if (string.slice(0, lastLine.length) != lastLine) continue search |
|||
for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++) |
|||
if (fold(doc.getLine(start + i)) != lines[i]) continue search |
|||
var top = doc.getLine(line + 1 - lines.length), topString = fold(top) |
|||
if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search |
|||
return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)), |
|||
to: Pos(line, adjustPos(orig, string, lastLine.length, fold))} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function SearchCursor(doc, query, pos, options) { |
|||
this.atOccurrence = false |
|||
this.doc = doc |
|||
pos = pos ? doc.clipPos(pos) : Pos(0, 0) |
|||
this.pos = {from: pos, to: pos} |
|||
|
|||
var caseFold |
|||
if (typeof options == "object") { |
|||
caseFold = options.caseFold |
|||
} else { // Backwards compat for when caseFold was the 4th argument
|
|||
caseFold = options |
|||
options = null |
|||
} |
|||
|
|||
if (typeof query == "string") { |
|||
if (caseFold == null) caseFold = false |
|||
this.matches = function(reverse, pos) { |
|||
return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold) |
|||
} |
|||
} else { |
|||
query = ensureFlags(query, "gm") |
|||
if (!options || options.multiline !== false) |
|||
this.matches = function(reverse, pos) { |
|||
return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos) |
|||
} |
|||
else |
|||
this.matches = function(reverse, pos) { |
|||
return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos) |
|||
} |
|||
} |
|||
} |
|||
|
|||
SearchCursor.prototype = { |
|||
findNext: function() {return this.find(false)}, |
|||
findPrevious: function() {return this.find(true)}, |
|||
|
|||
find: function(reverse) { |
|||
var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to)) |
|||
|
|||
// Implements weird auto-growing behavior on null-matches for
|
|||
// backwards-compatiblity with the vim code (unfortunately)
|
|||
while (result && CodeMirror.cmpPos(result.from, result.to) == 0) { |
|||
if (reverse) { |
|||
if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1) |
|||
else if (result.from.line == this.doc.firstLine()) result = null |
|||
else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1))) |
|||
} else { |
|||
if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1) |
|||
else if (result.to.line == this.doc.lastLine()) result = null |
|||
else result = this.matches(reverse, Pos(result.to.line + 1, 0)) |
|||
} |
|||
} |
|||
|
|||
if (result) { |
|||
this.pos = result |
|||
this.atOccurrence = true |
|||
return this.pos.match || true |
|||
} else { |
|||
var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0) |
|||
this.pos = {from: end, to: end} |
|||
return this.atOccurrence = false |
|||
} |
|||
}, |
|||
|
|||
from: function() {if (this.atOccurrence) return this.pos.from}, |
|||
to: function() {if (this.atOccurrence) return this.pos.to}, |
|||
|
|||
replace: function(newText, origin) { |
|||
if (!this.atOccurrence) return |
|||
var lines = CodeMirror.splitLines(newText) |
|||
this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin) |
|||
this.pos.to = Pos(this.pos.from.line + lines.length - 1, |
|||
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)) |
|||
} |
|||
} |
|||
|
|||
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { |
|||
return new SearchCursor(this.doc, query, pos, caseFold) |
|||
}) |
|||
CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { |
|||
return new SearchCursor(this, query, pos, caseFold) |
|||
}) |
|||
|
|||
CodeMirror.defineExtension("selectMatches", function(query, caseFold) { |
|||
var ranges = [] |
|||
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold) |
|||
while (cur.findNext()) { |
|||
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break |
|||
ranges.push({anchor: cur.from(), head: cur.to()}) |
|||
} |
|||
if (ranges.length) |
|||
this.setSelections(ranges, 0) |
|||
}) |
|||
}); |
|||
@ -0,0 +1,72 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
var WRAP_CLASS = "CodeMirror-activeline"; |
|||
var BACK_CLASS = "CodeMirror-activeline-background"; |
|||
var GUTT_CLASS = "CodeMirror-activeline-gutter"; |
|||
|
|||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) { |
|||
var prev = old == CodeMirror.Init ? false : old; |
|||
if (val == prev) return |
|||
if (prev) { |
|||
cm.off("beforeSelectionChange", selectionChange); |
|||
clearActiveLines(cm); |
|||
delete cm.state.activeLines; |
|||
} |
|||
if (val) { |
|||
cm.state.activeLines = []; |
|||
updateActiveLines(cm, cm.listSelections()); |
|||
cm.on("beforeSelectionChange", selectionChange); |
|||
} |
|||
}); |
|||
|
|||
function clearActiveLines(cm) { |
|||
for (var i = 0; i < cm.state.activeLines.length; i++) { |
|||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS); |
|||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS); |
|||
cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS); |
|||
} |
|||
} |
|||
|
|||
function sameArray(a, b) { |
|||
if (a.length != b.length) return false; |
|||
for (var i = 0; i < a.length; i++) |
|||
if (a[i] != b[i]) return false; |
|||
return true; |
|||
} |
|||
|
|||
function updateActiveLines(cm, ranges) { |
|||
var active = []; |
|||
for (var i = 0; i < ranges.length; i++) { |
|||
var range = ranges[i]; |
|||
var option = cm.getOption("styleActiveLine"); |
|||
if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty()) |
|||
continue |
|||
var line = cm.getLineHandleVisualStart(range.head.line); |
|||
if (active[active.length - 1] != line) active.push(line); |
|||
} |
|||
if (sameArray(cm.state.activeLines, active)) return; |
|||
cm.operation(function() { |
|||
clearActiveLines(cm); |
|||
for (var i = 0; i < active.length; i++) { |
|||
cm.addLineClass(active[i], "wrap", WRAP_CLASS); |
|||
cm.addLineClass(active[i], "background", BACK_CLASS); |
|||
cm.addLineClass(active[i], "gutter", GUTT_CLASS); |
|||
} |
|||
cm.state.activeLines = active; |
|||
}); |
|||
} |
|||
|
|||
function selectionChange(cm, sel) { |
|||
updateActiveLines(cm, sel.ranges); |
|||
} |
|||
}); |
|||
@ -0,0 +1,34 @@ |
|||
# diff |
|||
|
|||
implementation of myers diff algorithm |
|||
|
|||
[](https://travis-ci.org/Swatinem/diff) |
|||
[](https://coveralls.io/r/Swatinem/diff) |
|||
[](https://gemnasium.com/Swatinem/diff) |
|||
|
|||
|
|||
This uses the [*An O(ND) Difference Algorithm and Its Variations*](http://www.xmailserver.org/diff2.pdf) |
|||
Also see http://simplygenius.net/Article/DiffTutorial2 and |
|||
http://www.mathertel.de/Diff/ViewSrc.aspx for more inspiration |
|||
|
|||
## Installation |
|||
|
|||
$ npm install diff |
|||
$ component install Swatinem/diff |
|||
|
|||
## Usage |
|||
|
|||
### diff(a, b, [eql(a, b)]) |
|||
|
|||
Given two arrays (or array-likes, such as strings) `a` and `b` and an optional |
|||
equal function `eql`, this will return an array with the following operations: |
|||
* *nop* the element is in both arrays |
|||
* *ins* the element is only in array `b` and will be inserted |
|||
* *del* the element in only in array `a` and will be removed |
|||
* *rep* the element from `a` will be replaced by the element from `b`. |
|||
This is essentially the same as a del+ins |
|||
|
|||
## License |
|||
|
|||
LGPLv3 |
|||
|
|||
@ -0,0 +1,243 @@ |
|||
/******************************************************************************* |
|||
|
|||
Key portions of code below was borrowed from: |
|||
https://github.com/Swatinem/diff
|
|||
|
|||
License is LGPL3 (thanks!) as per: |
|||
https://github.com/Swatinem/diff/blob/b58391504759/README.md
|
|||
|
|||
I chose to pick this implementation over |
|||
https://github.com/google/diff-match-patch as suggested by CodeMirror
|
|||
because: |
|||
|
|||
- Code is clean and simple to read -- useful when unfamiliar with the diff |
|||
algorithm, this makes changing the code easier if/when needed. |
|||
|
|||
- Smaller -- diff_match_patch comes with an extended API most of which is |
|||
of no use to the current project. |
|||
- diff_match_patch uncompressed: 74.7 KB |
|||
- Swatinem's diff uncompressed: 3.66 KB |
|||
|
|||
- I can easily adapt Swatinem's diff to deal with arrays of strings, which |
|||
is best suited for the current project -- it natively work with arrays. |
|||
|
|||
I removed portions of code which are of no use for the current project. |
|||
|
|||
I modified the diff script generator (Diff.prototype.editscript) since I |
|||
need to generate a script which is compatible with the output of the |
|||
diff_match_patch, as expected by CodeMirror. |
|||
|
|||
2018-12-20 gorhill: |
|||
There was an issue causing the wrong diff data to be issued, for instance |
|||
when diff-ing these two URLs on a character granularity basis (failure |
|||
point is marked): |
|||
| |
|||
/articles/5c1a7aae1854f30006cb26f7/lede/1545239527833-shutterstock_726 01757 2-copy.jpeg?crop=0.8889xw%3A0.9988xh%3B0.1089xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
/articles/5c1a* 1854f30006cb2* /lede/15452* -shutterstock_* 017* 2-copy.jpeg?crop=0.* xw%3A* h%3B0.0* xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
/articles/5c1aaea91854f30006cb2f1e/lede/1545253629235-shutterstock_106399017 2-copy.jpeg?crop=0.7749xw%3A1 xh%3B0.0391xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
| |
|||
|
|||
Investigating, I found what appears to be the original source on which the |
|||
code below is based: |
|||
- "An O(ND) Difference Algorithm for C#" by Matthias Hertel |
|||
- http://www.mathertel.de/Diff/ViewSrc.aspx
|
|||
- https://github.com/mathertel
|
|||
|
|||
There was a difference; code had been commented out in the original source: |
|||
http://www.mathertel.de/Diff/DiffTest.aspx?oldfile=Diff.cs.v1&newfile=Diff.cs.v2
|
|||
|
|||
The developer noted: |
|||
> There have been overlapping boxes; that where analyzed partial differently. |
|||
> One return-point is enough. |
|||
|
|||
After applying the changes to the code below, the problematic diff-ing went |
|||
away: |
|||
| |
|||
/articles/5c1a7aae1854f30006cb26f7/lede/1545239527833-shutterstock_726 01757 2-copy.jpeg?crop=0.8889xw%3A0.9988xh%3B0.1089xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
/articles/5c1a* 1854f30006cb2* /lede/15452* -shutterstock_* 017* 2-copy.jpeg?crop=0.* 9xw%3A* xh%3B0.* xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
/articles/5c1aaea91854f30006cb2f1e/lede/1545253629235-shutterstock_106399017 2-copy.jpeg?crop=0.7749xw%3A1 xh%3B0.0391xw%2C0xh&resize=650%3A*&output-quality=55 |
|||
| |
|||
|
|||
So I will assume this was the issue. |
|||
|
|||
TODO: |
|||
- Apply other changes which were applied to the original code |
|||
|
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
(function(context) { |
|||
|
|||
// CodeMirror expect these globals:
|
|||
context.DIFF_INSERT = 1; |
|||
context.DIFF_DELETE = -1; |
|||
context.DIFF_EQUAL = 0; |
|||
context.diff_match_patch = function(){}; |
|||
|
|||
context.diff_match_patch.prototype.diff_main = function(a, b) { |
|||
if ( a === b ) { return [ [ 0, a ] ]; } |
|||
var aa = a.match(/\n|[^\n]+\n?/g) || []; |
|||
var bb = b.match(/\n|[^\n]+\n?/g) || []; |
|||
var d = new Diff(aa, bb, eqlDefault); |
|||
return d.editscript(); |
|||
}; |
|||
|
|||
function eqlDefault(a, b) { return a === b; } |
|||
|
|||
function Diff(a, b, eql) { |
|||
this.a = a; |
|||
this.b = b; |
|||
this.eql = eql; |
|||
|
|||
this.moda = Array.apply(null, new Array(a.length)).map(true.valueOf, false); |
|||
this.modb = Array.apply(null, new Array(b.length)).map(true.valueOf, false); |
|||
|
|||
// just to save some allocations:
|
|||
this.down = {}; |
|||
this.up = {}; |
|||
|
|||
this.lcs(0, a.length, 0, b.length); |
|||
} |
|||
|
|||
Diff.prototype.editscript = function Diff_editscript() { |
|||
var moda = this.moda, modb = this.modb; |
|||
var astart = 0, aend = moda.length; |
|||
var bstart = 0, bend = modb.length; |
|||
var result = []; |
|||
while (astart < aend || bstart < bend) { |
|||
if (astart < aend && bstart < bend) { |
|||
if (!moda[astart] && !modb[bstart]) { |
|||
result.push([ 0, this.a[astart] ]); |
|||
astart++; bstart++; |
|||
continue; |
|||
} else if (moda[astart] && modb[bstart]) { |
|||
result.push([ -1, this.a[astart] ]); |
|||
result.push([ 1, this.b[bstart] ]); |
|||
astart++; bstart++; |
|||
continue; |
|||
} |
|||
} |
|||
if (astart < aend && (bstart >= bend || moda[astart])) { |
|||
result.push([ -1, this.a[astart] ]); |
|||
astart++; |
|||
} |
|||
if (bstart < bend && (astart >= aend || modb[bstart])) { |
|||
result.push([ 1, this.b[bstart] ]); |
|||
bstart++; |
|||
} |
|||
} |
|||
return result; |
|||
}; |
|||
|
|||
Diff.prototype.lcs = function Diff_lcs(astart, aend, bstart, bend) { |
|||
var a = this.a, b = this.b, eql = this.eql; |
|||
// separate common head
|
|||
while (astart < aend && bstart < bend && eql(a[astart], b[bstart])) { |
|||
astart++; bstart++; |
|||
} |
|||
// separate common tail
|
|||
while (astart < aend && bstart < bend && eql(a[aend - 1], b[bend - 1])) { |
|||
aend--; bend--; |
|||
} |
|||
|
|||
if (astart === aend) { |
|||
// only insertions
|
|||
while (bstart < bend) { |
|||
this.modb[bstart] = true; |
|||
bstart++; |
|||
} |
|||
} else if (bend === bstart) { |
|||
// only deletions
|
|||
while (astart < aend) { |
|||
this.moda[astart] = true; |
|||
astart++; |
|||
} |
|||
} else { |
|||
var snake = this.snake(astart, aend, bstart, bend); |
|||
|
|||
this.lcs(astart, snake.x, bstart, snake.y); |
|||
this.lcs(snake.x, aend, snake.y, bend); |
|||
} |
|||
}; |
|||
|
|||
Diff.prototype.snake = function Diff_snake(astart, aend, bstart, bend) { |
|||
var a = this.a, b = this.b, eql = this.eql; |
|||
|
|||
var N = aend - astart, |
|||
M = bend - bstart; |
|||
|
|||
var kdown = astart - bstart; |
|||
var kup = aend - bend; |
|||
|
|||
var delta = N - M; |
|||
var deltaOdd = delta & 1; |
|||
|
|||
var down = this.down; |
|||
down[kdown + 1] = astart; |
|||
var up = this.up; |
|||
up[kup - 1] = aend; |
|||
|
|||
var Dmax = (N + M + 1) / 2; |
|||
for (var D = 0; D <= Dmax; D++) { |
|||
var k, x, y; |
|||
// forward path
|
|||
for (k = kdown - D; k <= kdown + D; k += 2) { |
|||
if (k === kdown - D) { |
|||
x = down[k + 1]; // down
|
|||
} else { |
|||
x = down[k - 1] + 1; // right
|
|||
if ((k < kdown + D) && (down[k + 1] >= x)) { |
|||
x = down[k + 1]; // down
|
|||
} |
|||
} |
|||
y = x - k; |
|||
|
|||
while (x < aend && y < bend && eql(a[x], b[y])) { |
|||
x++; y++; // diagonal
|
|||
} |
|||
down[k] = x; |
|||
|
|||
if (deltaOdd && (kup - D < k) && (k < kup + D) && |
|||
up[k] <= down[k]) { |
|||
return { |
|||
x: down[k], |
|||
y: down[k] - k, |
|||
// u: up[k],
|
|||
// v: up[k] - k,
|
|||
}; |
|||
} |
|||
} |
|||
|
|||
// reverse path
|
|||
for (k = kup - D; k <= kup + D; k += 2) { |
|||
if (k === kup + D) { |
|||
x = up[k - 1]; // up
|
|||
} else { |
|||
x = up[k + 1] - 1; // left
|
|||
if ((k > kup - D) && (up[k - 1] < x)) { |
|||
x = up[k - 1]; // up
|
|||
} |
|||
} |
|||
y = x - k; |
|||
|
|||
while (x > astart && y > bstart && eql(a[x - 1], b[y - 1])) { |
|||
x--; y--; // diagonal
|
|||
} |
|||
up[k] = x; |
|||
|
|||
if (!deltaOdd && (kdown - D <= k) && (k <= kdown + D) && |
|||
up[k] <= down[k]) { |
|||
return { |
|||
x: down[k], |
|||
y: down[k] - k, |
|||
// u: up[k],
|
|||
// v: up[k] - k,
|
|||
}; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
return Diff; |
|||
})(self); |
|||
@ -0,0 +1,52 @@ |
|||
## Purpose |
|||
|
|||
The purpose of this library is to implement LZ4 compression/decompression, |
|||
as documented at the official LZ4 repository: |
|||
|
|||
https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md |
|||
|
|||
The files in this directory are developed as a separate project at: |
|||
|
|||
https://github.com/gorhill/lz4-wasm |
|||
|
|||
## Files |
|||
|
|||
### `lz4-block-codec-any.js` |
|||
|
|||
The purpose is to instanciate a WebAssembly- or pure javascript-based |
|||
LZ4 block codec. |
|||
|
|||
If the choosen implementation is not specified, there will be an attempt to |
|||
create a WebAssembly-based instance. If for whatever reason this fails, a |
|||
pure javascript-based instance will be created. |
|||
|
|||
The script for either instance are dynamically loaded and only when needed, |
|||
such that no resources are wasted by keeping in memory code which won't be |
|||
used. |
|||
|
|||
### `lz4-block-codec-wasm.js` |
|||
|
|||
This contains the code to instanciate WebAssembly-based LZ4 block codec. Note |
|||
that the WebAssembly module is loaded using a `same-origin` fetch, hence |
|||
ensuring that no code outside the package is loaded. |
|||
|
|||
### `lz4-block-codec-js.js` |
|||
|
|||
This contains the code to instanciate pure javascript-based LZ4 block codec. |
|||
|
|||
This is used as a fallback implementation should WebAssembly not be available |
|||
for whatever reason. |
|||
|
|||
### `lz4-block-codec.wasm` |
|||
|
|||
This is the WebAssembly module, loaded by `lz4-block-codec-wasm.js` using a |
|||
`same-origin` fetch. |
|||
|
|||
### `lz4-block-codec.wat` |
|||
|
|||
The WebAssembly source code used to generate the WebAssembly module `lz4-block-codec.wasm`. |
|||
|
|||
wat2wasm ./lz4-block-codec.wat -o ./lz4-block-codec.wasm |
|||
wasm-opt ./lz4-block-codec.wasm -O4 -o ./lz4-block-codec.wasm |
|||
|
|||
You can get `wat2wasm` at <https://github.com/WebAssembly/wabt>, and `wasm-opt` at <https://github.com/WebAssembly/binaryen>. |
|||
@ -0,0 +1,171 @@ |
|||
/******************************************************************************* |
|||
|
|||
lz4-block-codec-any.js |
|||
A wrapper to instanciate a wasm- and/or js-based LZ4 block |
|||
encoder/decoder. |
|||
Copyright (C) 2018 Raymond Hill |
|||
|
|||
BSD-2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are |
|||
met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above |
|||
copyright notice, this list of conditions and the following disclaimer |
|||
in the documentation and/or other materials provided with the |
|||
distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
Home: https://github.com/gorhill/lz4-wasm
|
|||
|
|||
I used the same license as the one picked by creator of LZ4 out of respect |
|||
for his creation, see https://lz4.github.io/lz4/
|
|||
|
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
(function(context) { // >>>> Start of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
|
|||
let wd = (function() { |
|||
let url = document.currentScript.src; |
|||
let match = /[^\/]+$/.exec(url); |
|||
return match !== null ? |
|||
url.slice(0, match.index) : |
|||
''; |
|||
})(); |
|||
|
|||
let removeScript = function(script) { |
|||
if ( !script ) { return; } |
|||
if ( script.parentNode === null ) { return; } |
|||
script.parentNode.removeChild(script); |
|||
}; |
|||
|
|||
let createInstanceWASM = function() { |
|||
if ( context.LZ4BlockWASM instanceof Function ) { |
|||
let instance = new context.LZ4BlockWASM(); |
|||
return instance.init().then(( ) => { return instance; }); |
|||
} |
|||
if ( context.LZ4BlockWASM === null ) { |
|||
return Promise.resolve(null); |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
let script = document.createElement('script'); |
|||
script.src = wd + 'lz4-block-codec-wasm.js'; |
|||
script.addEventListener('load', ( ) => { |
|||
if ( context.LZ4BlockWASM instanceof Function === false ) { |
|||
context.LZ4BlockWASM = null; |
|||
context.LZ4BlockWASM = undefined; |
|||
resolve(null); |
|||
} else { |
|||
let instance = new context.LZ4BlockWASM(); |
|||
instance.init() |
|||
.then(( ) => { |
|||
resolve(instance); |
|||
}) |
|||
.catch(error => { |
|||
reject(error); |
|||
}); |
|||
} |
|||
}); |
|||
script.addEventListener('error', ( ) => { |
|||
context.LZ4BlockWASM = null; |
|||
resolve(null); |
|||
}); |
|||
document.head.appendChild(script); |
|||
removeScript(script); |
|||
}); |
|||
}; |
|||
|
|||
let createInstanceJS = function() { |
|||
if ( context.LZ4BlockJS instanceof Function ) { |
|||
let instance = new context.LZ4BlockJS(); |
|||
return instance.init().then(( ) => { return instance; }); |
|||
} |
|||
if ( context.LZ4BlockJS === null ) { |
|||
return Promise.resolve(null); |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
let script = document.createElement('script'); |
|||
script.src = wd + 'lz4-block-codec-js.js'; |
|||
script.addEventListener('load', ( ) => { |
|||
if ( context.LZ4BlockJS instanceof Function === false ) { |
|||
context.LZ4BlockJS = null; |
|||
resolve(null); |
|||
} else { |
|||
let instance = new context.LZ4BlockJS(); |
|||
instance.init() |
|||
.then(( ) => { |
|||
resolve(instance); |
|||
}) |
|||
.catch(error => { |
|||
reject(error); |
|||
}); |
|||
} |
|||
}); |
|||
script.addEventListener('error', ( ) => { |
|||
context.LZ4BlockJS = null; |
|||
resolve(null); |
|||
}); |
|||
document.head.appendChild(script); |
|||
removeScript(script); |
|||
}); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
context.lz4BlockCodec = { |
|||
createInstance: function(flavor) { |
|||
let instantiator; |
|||
if ( flavor === 'wasm' ) { |
|||
instantiator = createInstanceWASM; |
|||
} else if ( flavor === 'js' ) { |
|||
instantiator = createInstanceJS; |
|||
} else { |
|||
instantiator = createInstanceWASM || createInstanceJS; |
|||
} |
|||
return (instantiator)() |
|||
.then(instance => { |
|||
if ( instance ) { return instance; } |
|||
if ( flavor === undefined ) { |
|||
return createInstanceJS(); |
|||
} |
|||
return null; |
|||
}) |
|||
.catch(( ) => { |
|||
if ( flavor === undefined ) { |
|||
return createInstanceJS(); |
|||
} |
|||
return null; |
|||
}); |
|||
}, |
|||
reset: function() { |
|||
context.LZ4BlockWASM = undefined; |
|||
context.LZ4BlockJS = undefined; |
|||
} |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(this || self); // <<<< End of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
@ -0,0 +1,297 @@ |
|||
/******************************************************************************* |
|||
|
|||
lz4-block-codec-js.js |
|||
A javascript wrapper around a pure javascript implementation of |
|||
LZ4 block format codec. |
|||
Copyright (C) 2018 Raymond Hill |
|||
|
|||
BSD-2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are |
|||
met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above |
|||
copyright notice, this list of conditions and the following disclaimer |
|||
in the documentation and/or other materials provided with the |
|||
distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
Home: https://github.com/gorhill/lz4-wasm
|
|||
|
|||
I used the same license as the one picked by creator of LZ4 out of respect |
|||
for his creation, see https://lz4.github.io/lz4/
|
|||
|
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
(function(context) { // >>>> Start of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
|
|||
let growOutputBuffer = function(instance, size) { |
|||
if ( |
|||
instance.outputBuffer === undefined || |
|||
instance.outputBuffer.byteLength < size |
|||
) { |
|||
instance.outputBuffer = new ArrayBuffer(size + 0xFFFF & 0x7FFF0000); |
|||
} |
|||
return instance.outputBuffer; |
|||
}; |
|||
|
|||
let encodeBound = function(size) { |
|||
return size > 0x7E000000 ? |
|||
0 : |
|||
size + (size / 255 | 0) + 16; |
|||
}; |
|||
|
|||
let encodeBlock = function(instance, iBuf, oOffset) { |
|||
let iLen = iBuf.byteLength; |
|||
if ( iLen >= 0x7E000000 ) { throw new RangeError(); } |
|||
|
|||
// "The last match must start at least 12 bytes before end of block"
|
|||
let lastMatchPos = iLen - 12; |
|||
|
|||
// "The last 5 bytes are always literals"
|
|||
let lastLiteralPos = iLen - 5; |
|||
|
|||
if ( instance.hashTable === undefined ) { |
|||
instance.hashTable = new Int32Array(65536); |
|||
} |
|||
instance.hashTable.fill(-65536); |
|||
|
|||
if ( iBuf instanceof ArrayBuffer ) { |
|||
iBuf = new Uint8Array(iBuf); |
|||
} |
|||
|
|||
let oLen = oOffset + encodeBound(iLen); |
|||
let oBuf = new Uint8Array(growOutputBuffer(instance, oLen), 0, oLen); |
|||
let iPos = 0; |
|||
let oPos = oOffset; |
|||
let anchorPos = 0; |
|||
|
|||
// sequence-finding loop
|
|||
for (;;) { |
|||
let refPos; |
|||
let mOffset; |
|||
let sequence = iBuf[iPos] << 8 | iBuf[iPos+1] << 16 | iBuf[iPos+2] << 24; |
|||
|
|||
// match-finding loop
|
|||
while ( iPos <= lastMatchPos ) { |
|||
sequence = sequence >>> 8 | iBuf[iPos+3] << 24; |
|||
let hash = (sequence * 0x9E37 & 0xFFFF) + (sequence * 0x79B1 >>> 16) & 0xFFFF; |
|||
refPos = instance.hashTable[hash]; |
|||
instance.hashTable[hash] = iPos; |
|||
mOffset = iPos - refPos; |
|||
if ( |
|||
mOffset < 65536 && |
|||
iBuf[refPos+0] === ((sequence ) & 0xFF) && |
|||
iBuf[refPos+1] === ((sequence >>> 8) & 0xFF) && |
|||
iBuf[refPos+2] === ((sequence >>> 16) & 0xFF) && |
|||
iBuf[refPos+3] === ((sequence >>> 24) & 0xFF) |
|||
) { |
|||
break; |
|||
} |
|||
iPos += 1; |
|||
} |
|||
|
|||
// no match found
|
|||
if ( iPos > lastMatchPos ) { break; } |
|||
|
|||
// match found
|
|||
let lLen = iPos - anchorPos; |
|||
let mLen = iPos; |
|||
iPos += 4; refPos += 4; |
|||
while ( iPos < lastLiteralPos && iBuf[iPos] === iBuf[refPos] ) { |
|||
iPos += 1; refPos += 1; |
|||
} |
|||
mLen = iPos - mLen; |
|||
let token = mLen < 19 ? mLen - 4 : 15; |
|||
|
|||
// write token, length of literals if needed
|
|||
if ( lLen >= 15 ) { |
|||
oBuf[oPos++] = 0xF0 | token; |
|||
let l = lLen - 15; |
|||
while ( l >= 255 ) { |
|||
oBuf[oPos++] = 255; |
|||
l -= 255; |
|||
} |
|||
oBuf[oPos++] = l; |
|||
} else { |
|||
oBuf[oPos++] = (lLen << 4) | token; |
|||
} |
|||
|
|||
// write literals
|
|||
while ( lLen-- ) { |
|||
oBuf[oPos++] = iBuf[anchorPos++]; |
|||
} |
|||
|
|||
if ( mLen === 0 ) { break; } |
|||
|
|||
// write offset of match
|
|||
oBuf[oPos+0] = mOffset; |
|||
oBuf[oPos+1] = mOffset >>> 8; |
|||
oPos += 2; |
|||
|
|||
// write length of match if needed
|
|||
if ( mLen >= 19 ) { |
|||
let l = mLen - 19; |
|||
while ( l >= 255 ) { |
|||
oBuf[oPos++] = 255; |
|||
l -= 255; |
|||
} |
|||
oBuf[oPos++] = l; |
|||
} |
|||
|
|||
anchorPos = iPos; |
|||
} |
|||
|
|||
// last sequence is literals only
|
|||
let lLen = iLen - anchorPos; |
|||
if ( lLen >= 15 ) { |
|||
oBuf[oPos++] = 0xF0; |
|||
let l = lLen - 15; |
|||
while ( l >= 255 ) { |
|||
oBuf[oPos++] = 255; |
|||
l -= 255; |
|||
} |
|||
oBuf[oPos++] = l; |
|||
} else { |
|||
oBuf[oPos++] = lLen << 4; |
|||
} |
|||
while ( lLen-- ) { |
|||
oBuf[oPos++] = iBuf[anchorPos++]; |
|||
} |
|||
|
|||
return new Uint8Array(oBuf.buffer, 0, oPos); |
|||
}; |
|||
|
|||
let decodeBlock = function(instance, iBuf, iOffset, oLen) { |
|||
let iLen = iBuf.byteLength; |
|||
let oBuf = new Uint8Array(growOutputBuffer(instance, oLen), 0, oLen); |
|||
let iPos = iOffset, oPos = 0; |
|||
|
|||
while ( iPos < iLen ) { |
|||
let token = iBuf[iPos++]; |
|||
|
|||
// literals
|
|||
let clen = token >>> 4; |
|||
|
|||
// length of literals
|
|||
if ( clen !== 0 ) { |
|||
if ( clen === 15 ) { |
|||
let l; |
|||
for (;;) { |
|||
l = iBuf[iPos++]; |
|||
if ( l !== 255 ) { break; } |
|||
clen += 255; |
|||
} |
|||
clen += l; |
|||
} |
|||
|
|||
// copy literals
|
|||
let end = iPos + clen; |
|||
while ( iPos < end ) { |
|||
oBuf[oPos++] = iBuf[iPos++]; |
|||
} |
|||
if ( iPos === iLen ) { break; } |
|||
} |
|||
|
|||
// match
|
|||
let mOffset = iBuf[iPos+0] | (iBuf[iPos+1] << 8); |
|||
if ( mOffset === 0 || mOffset > oPos ) { return; } |
|||
iPos += 2; |
|||
|
|||
// length of match
|
|||
clen = (token & 0x0F) + 4; |
|||
if ( clen === 19 ) { |
|||
let l; |
|||
for (;;) { |
|||
l = iBuf[iPos++]; |
|||
if ( l !== 255 ) { break; } |
|||
clen += 255; |
|||
} |
|||
clen += l; |
|||
} |
|||
|
|||
// copy match
|
|||
let mPos = oPos - mOffset; |
|||
let end = oPos + clen; |
|||
while ( oPos < end ) { |
|||
oBuf[oPos++] = oBuf[mPos++]; |
|||
} |
|||
} |
|||
|
|||
return oBuf; |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
context.LZ4BlockJS = function() { |
|||
this.hashTable = undefined; |
|||
this.outputBuffer = undefined; |
|||
}; |
|||
|
|||
context.LZ4BlockJS.prototype = { |
|||
flavor: 'js', |
|||
init: function() { |
|||
return Promise.resolve(); |
|||
}, |
|||
|
|||
reset: function() { |
|||
this.hashTable = undefined; |
|||
this.outputBuffer = undefined; |
|||
}, |
|||
|
|||
bytesInUse: function() { |
|||
let bytesInUse = 0; |
|||
if ( this.hashTable !== undefined ) { |
|||
bytesInUse += this.hashTable.byteLength; |
|||
} |
|||
if ( this.outputBuffer !== undefined ) { |
|||
bytesInUse += this.outputBuffer.byteLength; |
|||
} |
|||
return bytesInUse; |
|||
}, |
|||
|
|||
encodeBlock: function(input, outputOffset) { |
|||
if ( input instanceof ArrayBuffer ) { |
|||
input = new Uint8Array(input); |
|||
} else if ( input instanceof Uint8Array === false ) { |
|||
throw new TypeError(); |
|||
} |
|||
return encodeBlock(this, input, outputOffset); |
|||
}, |
|||
|
|||
decodeBlock: function(input, inputOffset, outputSize) { |
|||
if ( input instanceof ArrayBuffer ) { |
|||
input = new Uint8Array(input); |
|||
} else if ( input instanceof Uint8Array === false ) { |
|||
throw new TypeError(); |
|||
} |
|||
return decodeBlock(this, input, inputOffset, outputSize); |
|||
} |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(this || self); // <<<< End of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
@ -0,0 +1,194 @@ |
|||
/******************************************************************************* |
|||
|
|||
lz4-block-codec-wasm.js |
|||
A javascript wrapper around a WebAssembly implementation of |
|||
LZ4 block format codec. |
|||
Copyright (C) 2018 Raymond Hill |
|||
|
|||
BSD-2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are |
|||
met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above |
|||
copyright notice, this list of conditions and the following disclaimer |
|||
in the documentation and/or other materials provided with the |
|||
distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
Home: https://github.com/gorhill/lz4-wasm
|
|||
|
|||
I used the same license as the one picked by creator of LZ4 out of respect |
|||
for his creation, see https://lz4.github.io/lz4/
|
|||
|
|||
*/ |
|||
|
|||
/* global WebAssembly */ |
|||
|
|||
'use strict'; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
(function(context) { // >>>> Start of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
|
|||
let wd = (function() { |
|||
let url = document.currentScript.src; |
|||
let match = /[^\/]+$/.exec(url); |
|||
return match !== null ? |
|||
url.slice(0, match.index) : |
|||
''; |
|||
})(); |
|||
|
|||
let growMemoryTo = function(wasmInstance, byteLength) { |
|||
let lz4api = wasmInstance.exports; |
|||
let neededByteLength = lz4api.getLinearMemoryOffset() + byteLength; |
|||
let pageCountBefore = lz4api.memory.buffer.byteLength >>> 16; |
|||
let pageCountAfter = (neededByteLength + 65535) >>> 16; |
|||
if ( pageCountAfter > pageCountBefore ) { |
|||
lz4api.memory.grow(pageCountAfter - pageCountBefore); |
|||
} |
|||
return lz4api.memory.buffer; |
|||
}; |
|||
|
|||
let encodeBlock = function(wasmInstance, inputArray, outputOffset) { |
|||
let lz4api = wasmInstance.exports; |
|||
let mem0 = lz4api.getLinearMemoryOffset(); |
|||
let hashTableSize = 65536 * 4; |
|||
let inputSize = inputArray.byteLength; |
|||
if ( inputSize >= 0x7E000000 ) { throw new RangeError(); } |
|||
let memSize = |
|||
hashTableSize + |
|||
inputSize + |
|||
outputOffset + lz4api.lz4BlockEncodeBound(inputSize); |
|||
let memBuffer = growMemoryTo(wasmInstance, memSize); |
|||
let hashTable = new Int32Array(memBuffer, mem0, 65536); |
|||
hashTable.fill(-65536, 0, 65536); |
|||
let inputMem = new Uint8Array(memBuffer, mem0 + hashTableSize, inputSize); |
|||
inputMem.set(inputArray); |
|||
let outputSize = lz4api.lz4BlockEncode( |
|||
mem0 + hashTableSize, |
|||
inputSize, |
|||
mem0 + hashTableSize + inputSize + outputOffset |
|||
); |
|||
if ( outputSize === 0 ) { return; } |
|||
let outputArray = new Uint8Array( |
|||
memBuffer, |
|||
mem0 + hashTableSize + inputSize, |
|||
outputOffset + outputSize |
|||
); |
|||
return outputArray; |
|||
}; |
|||
|
|||
let decodeBlock = function(wasmInstance, inputArray, inputOffset, outputSize) { |
|||
let inputSize = inputArray.byteLength; |
|||
let lz4api = wasmInstance.exports; |
|||
let mem0 = lz4api.getLinearMemoryOffset(); |
|||
let memSize = inputSize + outputSize; |
|||
let memBuffer = growMemoryTo(wasmInstance, memSize); |
|||
let inputArea = new Uint8Array(memBuffer, mem0, inputSize); |
|||
inputArea.set(inputArray); |
|||
outputSize = lz4api.lz4BlockDecode( |
|||
mem0 + inputOffset, |
|||
inputSize - inputOffset, |
|||
mem0 + inputSize |
|||
); |
|||
if ( outputSize === 0 ) { return; } |
|||
return new Uint8Array(memBuffer, mem0 + inputSize, outputSize); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
context.LZ4BlockWASM = function() { |
|||
this.lz4wasmInstance = undefined; |
|||
}; |
|||
|
|||
context.LZ4BlockWASM.prototype = { |
|||
flavor: 'wasm', |
|||
|
|||
init: function() { |
|||
if ( |
|||
typeof WebAssembly !== 'object' || |
|||
typeof WebAssembly.instantiateStreaming !== 'function' |
|||
) { |
|||
this.lz4wasmInstance = null; |
|||
} |
|||
if ( this.lz4wasmInstance === null ) { |
|||
return Promise.reject(); |
|||
} |
|||
if ( this.lz4wasmInstance instanceof WebAssembly.Instance ) { |
|||
return Promise.resolve(this.lz4wasmInstance); |
|||
} |
|||
if ( this.lz4wasmInstance === undefined ) { |
|||
this.lz4wasmInstance = WebAssembly.instantiateStreaming( |
|||
fetch(wd + 'lz4-block-codec.wasm', { mode: 'same-origin' }) |
|||
).then(result => { |
|||
this.lz4wasmInstance = undefined; |
|||
this.lz4wasmInstance = result && result.instance || null; |
|||
if ( this.lz4wasmInstance !== null ) { return this; } |
|||
return null; |
|||
}); |
|||
this.lz4wasmInstance.catch(( ) => { |
|||
this.lz4wasmInstance = null; |
|||
return null; |
|||
}); |
|||
} |
|||
return this.lz4wasmInstance; |
|||
}, |
|||
|
|||
reset: function() { |
|||
this.lz4wasmInstance = undefined; |
|||
}, |
|||
|
|||
bytesInUse: function() { |
|||
return this.lz4wasmInstance instanceof WebAssembly.Instance ? |
|||
this.lz4wasmInstance.exports.memory.buffer.byteLength : |
|||
0; |
|||
}, |
|||
|
|||
encodeBlock: function(input, outputOffset) { |
|||
if ( this.lz4wasmInstance instanceof WebAssembly.Instance === false ) { |
|||
throw new Error('LZ4BlockWASM: not initialized'); |
|||
} |
|||
if ( input instanceof ArrayBuffer ) { |
|||
input = new Uint8Array(input); |
|||
} else if ( input instanceof Uint8Array === false ) { |
|||
throw new TypeError(); |
|||
} |
|||
return encodeBlock(this.lz4wasmInstance, input, outputOffset); |
|||
}, |
|||
|
|||
decodeBlock: function(input, inputOffset, outputSize) { |
|||
if ( this.lz4wasmInstance instanceof WebAssembly.Instance === false ) { |
|||
throw new Error('LZ4BlockWASM: not initialized'); |
|||
} |
|||
if ( input instanceof ArrayBuffer ) { |
|||
input = new Uint8Array(input); |
|||
} else if ( input instanceof Uint8Array === false ) { |
|||
throw new TypeError(); |
|||
} |
|||
return decodeBlock(this.lz4wasmInstance, input, inputOffset, outputSize); |
|||
} |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(this || self); // <<<< End of private namespace
|
|||
|
|||
/******************************************************************************/ |
|||
@ -0,0 +1,745 @@ |
|||
;; |
|||
;; lz4-block-codec.wat: a WebAssembly implementation of LZ4 block format codec |
|||
;; Copyright (C) 2018 Raymond Hill |
|||
;; |
|||
;; BSD-2-Clause License (http://www.opensource.org/licenses/bsd-license.php) |
|||
;; |
|||
;; Redistribution and use in source and binary forms, with or without |
|||
;; modification, are permitted provided that the following conditions are |
|||
;; met: |
|||
;; |
|||
;; 1. Redistributions of source code must retain the above copyright |
|||
;; notice, this list of conditions and the following disclaimer. |
|||
;; |
|||
;; 2. Redistributions in binary form must reproduce the above |
|||
;; copyright notice, this list of conditions and the following disclaimer |
|||
;; in the documentation and/or other materials provided with the |
|||
;; distribution. |
|||
;; |
|||
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
;; |
|||
;; Home: https://github.com/gorhill/lz4-wasm |
|||
;; |
|||
;; I used the same license as the one picked by creator of LZ4 out of respect |
|||
;; for his creation, see https://lz4.github.io/lz4/ |
|||
;; |
|||
|
|||
(module |
|||
;; |
|||
;; module start |
|||
;; |
|||
|
|||
;; (func $log (import "imports" "log") (param i32 i32 i32)) |
|||
|
|||
(memory (export "memory") 1) |
|||
|
|||
;; |
|||
;; Public functions |
|||
;; |
|||
|
|||
;; |
|||
;; Return an offset to the first byte of usable linear memory. |
|||
;; Might be useful in the future to reserve memory space for whatever purpose, |
|||
;; like config variables, etc. |
|||
;; |
|||
(func $getLinearMemoryOffset (export "getLinearMemoryOffset") |
|||
(result i32) |
|||
i32.const 0 |
|||
) |
|||
|
|||
;; |
|||
;; unsigned int lz4BlockEncodeBound() |
|||
;; |
|||
;; Return the maximum size of the output buffer holding the compressed data. |
|||
;; |
|||
;; Reference implementation: |
|||
;; https://github.com/lz4/lz4/blob/dev/lib/lz4.h#L156 |
|||
;; |
|||
(func (export "lz4BlockEncodeBound") |
|||
(param $ilen i32) |
|||
(result i32) |
|||
get_local $ilen |
|||
i32.const 0x7E000000 |
|||
i32.gt_u |
|||
if |
|||
i32.const 0 |
|||
return |
|||
end |
|||
get_local $ilen |
|||
get_local $ilen |
|||
i32.const 255 |
|||
i32.div_u |
|||
i32.add |
|||
i32.const 16 |
|||
i32.add |
|||
) |
|||
|
|||
;; |
|||
;; unsigned int lz4BlockEncode( |
|||
;; unsigned int inPtr, |
|||
;; unsigned int ilen, |
|||
;; unsigned int outPtr |
|||
;; ) |
|||
;; |
|||
;; https://github.com/lz4/lz4/blob/dev/lib/lz4.c#L651 |
|||
;; |
|||
;; The implementation below is modified from the reference one. |
|||
;; |
|||
;; - There is no skip adjustement for repeated failure to find a match. |
|||
;; |
|||
;; - All configurable values are hard-coded to match the generic version |
|||
;; of the compressor. |
|||
;; |
|||
;; Note the size of the input block is NOT encoded in the output buffer, it |
|||
;; is for the caller to figure how they will save that information on |
|||
;; their side. At this point it is probably a trivial amount of work to |
|||
;; implement the LZ4 frame format, which encode the content size, but this |
|||
;; is for another day. |
|||
;; |
|||
(func $lz4BlockEncode (export "lz4BlockEncode") |
|||
(param $inPtr i32) ;; pointer to start of input buffer |
|||
(param $ilen i32) ;; size of input buffer |
|||
(param $outPtr i32) ;; pointer to start of output buffer |
|||
(result i32) |
|||
(local $hashPtrBeg i32) ;; start of hash buffer |
|||
(local $hashPtr i32) ;; current hash entry |
|||
(local $anchorPtr i32) ;; anchor position in input |
|||
(local $inPtrEnd1 i32) ;; point in input at which match-finding must cease |
|||
(local $inPtrEnd2 i32) ;; point in input at which match-length finding must cease |
|||
(local $inPtrEnd i32) ;; point to end of input |
|||
(local $outPtrBeg i32) ;; start of output buffer |
|||
(local $refPtr i32) ;; start of match in input |
|||
(local $seq32 i32) ;; 4-byte value from current input position |
|||
(local $llen i32) ;; length of found literals |
|||
(local $moffset i32) ;; offset to found match from current input position |
|||
(local $mlen i32) ;; length of found match |
|||
get_local $ilen ;; empty input = empty output |
|||
i32.const 0x7E000000 ;; max input size: 0x7E000000 |
|||
i32.gt_u |
|||
if |
|||
i32.const 0 |
|||
return |
|||
end |
|||
get_local $ilen ;; "blocks < 13 bytes cannot be compressed" |
|||
i32.const 13 |
|||
i32.lt_u |
|||
if |
|||
i32.const 0 |
|||
return |
|||
end |
|||
call $getLinearMemoryOffset ;; hash table is at start of usable memory |
|||
set_local $hashPtrBeg |
|||
get_local $inPtr |
|||
tee_local $anchorPtr |
|||
get_local $ilen |
|||
i32.add |
|||
tee_local $inPtrEnd |
|||
i32.const -5 ;; "The last 5 bytes are always literals." |
|||
i32.add |
|||
tee_local $inPtrEnd2 |
|||
i32.const -7 ;; "The last match must start at least 12 bytes before end of block" |
|||
i32.add |
|||
set_local $inPtrEnd1 |
|||
get_local $outPtr |
|||
set_local $outPtrBeg |
|||
;; |
|||
;; sequence processing loop |
|||
;; |
|||
block $noMoreSequence loop $nextSequence |
|||
get_local $inPtr |
|||
get_local $inPtrEnd1 |
|||
i32.ge_u ;; 5 or less bytes left? |
|||
br_if $noMoreSequence |
|||
get_local $inPtr ;; first sequence of 3 bytes before match-finding loop |
|||
i32.load8_u |
|||
i32.const 8 |
|||
i32.shl |
|||
get_local $inPtr |
|||
i32.load8_u offset=1 |
|||
i32.const 16 |
|||
i32.shl |
|||
i32.or |
|||
get_local $inPtr |
|||
i32.load8_u offset=2 |
|||
i32.const 24 |
|||
i32.shl |
|||
i32.or |
|||
set_local $seq32 |
|||
;; |
|||
;; match-finding loop |
|||
;; |
|||
loop $findMatch block $noMatchFound |
|||
get_local $inPtr |
|||
get_local $inPtrEnd2 |
|||
i32.gt_u ;; less than 12 bytes left? |
|||
br_if $noMoreSequence |
|||
get_local $seq32 ;; update last byte of current sequence |
|||
i32.const 8 |
|||
i32.shr_u |
|||
get_local $inPtr |
|||
i32.load8_u offset=3 |
|||
i32.const 24 |
|||
i32.shl |
|||
i32.or |
|||
tee_local $seq32 |
|||
i32.const 0x9E3779B1 ;; compute 16-bit hash |
|||
i32.mul |
|||
i32.const 16 |
|||
i32.shr_u ;; hash value is at top of stack |
|||
i32.const 2 ;; lookup refPtr at hash entry |
|||
i32.shl |
|||
get_local $hashPtrBeg |
|||
i32.add |
|||
tee_local $hashPtr |
|||
i32.load |
|||
set_local $refPtr |
|||
get_local $hashPtr ;; update hash entry with inPtr |
|||
get_local $inPtr |
|||
i32.store |
|||
get_local $inPtr |
|||
get_local $refPtr |
|||
i32.sub |
|||
tee_local $moffset ;; remember match offset, we will need it in case of match |
|||
i32.const 0xFFFF |
|||
i32.gt_s ;; match offset > 65535 = unusable match |
|||
br_if $noMatchFound |
|||
;; |
|||
;; confirm match: different sequences can yield same hash |
|||
;; compare-branch each byte to potentially save memory read ops |
|||
;; |
|||
get_local $seq32 ;; byte 0 |
|||
i32.const 0xFF |
|||
i32.and |
|||
get_local $refPtr |
|||
i32.load8_u |
|||
i32.ne ;; refPtr[0] !== inPtr[0] |
|||
br_if $noMatchFound |
|||
get_local $seq32 ;; byte 1 |
|||
i32.const 8 |
|||
i32.shr_u |
|||
i32.const 0xFF |
|||
i32.and |
|||
get_local $refPtr |
|||
i32.load8_u offset=1 |
|||
i32.ne |
|||
br_if $noMatchFound ;; refPtr[1] !== inPtr[1] |
|||
get_local $seq32 ;; byte 2 |
|||
i32.const 16 |
|||
i32.shr_u |
|||
i32.const 0xFF |
|||
i32.and |
|||
get_local $refPtr |
|||
i32.load8_u offset=2 |
|||
i32.ne ;; refPtr[2] !== inPtr[2] |
|||
br_if $noMatchFound |
|||
get_local $seq32 ;; byte 3 |
|||
i32.const 24 |
|||
i32.shr_u |
|||
i32.const 0xFF |
|||
i32.and |
|||
get_local $refPtr |
|||
i32.load8_u offset=3 |
|||
i32.ne ;; refPtr[3] !== inPtr[3] |
|||
br_if $noMatchFound |
|||
;; |
|||
;; a valid match has been found at this point |
|||
;; |
|||
get_local $inPtr ;; compute length of literals |
|||
get_local $anchorPtr |
|||
i32.sub |
|||
set_local $llen |
|||
get_local $inPtr ;; find match length |
|||
i32.const 4 ;; skip over confirmed 4-byte match |
|||
i32.add |
|||
set_local $inPtr |
|||
get_local $refPtr |
|||
i32.const 4 |
|||
i32.add |
|||
tee_local $mlen ;; remember refPtr to later compute match length |
|||
set_local $refPtr |
|||
block $endOfMatch loop ;; scan input buffer until match ends |
|||
get_local $inPtr |
|||
get_local $inPtrEnd2 |
|||
i32.ge_u |
|||
br_if $endOfMatch |
|||
get_local $inPtr |
|||
i32.load8_u |
|||
get_local $refPtr |
|||
i32.load8_u |
|||
i32.ne |
|||
br_if $endOfMatch |
|||
get_local $inPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $inPtr |
|||
get_local $refPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $refPtr |
|||
br 0 |
|||
end end $endOfMatch |
|||
;; encode token |
|||
get_local $outPtr ;; output token |
|||
get_local $llen |
|||
get_local $refPtr |
|||
get_local $mlen |
|||
i32.sub |
|||
tee_local $mlen |
|||
call $writeToken |
|||
get_local $outPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $outPtr |
|||
get_local $llen ;; encode/write length of literals if needed |
|||
i32.const 15 |
|||
i32.ge_s |
|||
if |
|||
get_local $outPtr |
|||
get_local $llen |
|||
call $writeLength |
|||
set_local $outPtr |
|||
end |
|||
;; copy literals |
|||
get_local $outPtr |
|||
get_local $anchorPtr |
|||
get_local $llen |
|||
call $copy |
|||
get_local $outPtr |
|||
get_local $llen |
|||
i32.add |
|||
set_local $outPtr |
|||
;; encode match offset |
|||
get_local $outPtr |
|||
get_local $moffset |
|||
i32.store8 |
|||
get_local $outPtr |
|||
get_local $moffset |
|||
i32.const 8 |
|||
i32.shr_u |
|||
i32.store8 offset=1 |
|||
get_local $outPtr |
|||
i32.const 2 |
|||
i32.add |
|||
set_local $outPtr |
|||
get_local $mlen ;; encode/write length of match if needed |
|||
i32.const 15 |
|||
i32.ge_s |
|||
if |
|||
get_local $outPtr |
|||
get_local $mlen |
|||
call $writeLength |
|||
set_local $outPtr |
|||
end |
|||
get_local $inPtr ;; advance anchor to current position |
|||
set_local $anchorPtr |
|||
br $nextSequence |
|||
end $noMatchFound |
|||
get_local $inPtr ;; no match found: advance to next byte |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $inPtr |
|||
br $findMatch end ;; match offset > 65535 = unusable match |
|||
end end $noMoreSequence |
|||
;; |
|||
;; generate last (match-less) sequence if compression succeeded |
|||
;; |
|||
get_local $outPtr |
|||
get_local $outPtrBeg |
|||
i32.eq |
|||
if |
|||
i32.const 0 |
|||
return |
|||
end |
|||
get_local $outPtr |
|||
get_local $inPtrEnd |
|||
get_local $anchorPtr |
|||
i32.sub |
|||
tee_local $llen |
|||
i32.const 0 |
|||
call $writeToken |
|||
get_local $outPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $outPtr |
|||
get_local $llen |
|||
i32.const 15 |
|||
i32.ge_u |
|||
if |
|||
get_local $outPtr |
|||
get_local $llen |
|||
call $writeLength |
|||
set_local $outPtr |
|||
end |
|||
get_local $outPtr |
|||
get_local $anchorPtr |
|||
get_local $llen |
|||
call $copy |
|||
get_local $outPtr ;; return number of written bytes |
|||
get_local $llen |
|||
i32.add |
|||
get_local $outPtrBeg |
|||
i32.sub |
|||
) |
|||
|
|||
;; |
|||
;; unsigned int lz4BlockDecode( |
|||
;; unsigned int inPtr, |
|||
;; unsigned int ilen |
|||
;; unsigned int outPtr |
|||
;; ) |
|||
;; |
|||
;; Reference: |
|||
;; https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md |
|||
;; |
|||
(func (export "lz4BlockDecode") |
|||
(param $inPtr0 i32) ;; start of input buffer |
|||
(param $ilen i32) ;; length of input buffer |
|||
(param $outPtr0 i32) ;; start of output buffer |
|||
(result i32) |
|||
(local $inPtr i32) ;; current position in input buffer |
|||
(local $inPtrEnd i32) ;; end of input buffer |
|||
(local $outPtr i32) ;; current position in output buffer |
|||
(local $matchPtr i32) ;; position of current match |
|||
(local $token i32) ;; sequence token |
|||
(local $clen i32) ;; number of bytes to copy |
|||
(local $_ i32) ;; general purpose variable |
|||
get_local $ilen ;; if ( ilen == 0 ) { return 0; } |
|||
i32.eqz |
|||
if |
|||
i32.const 0 |
|||
return |
|||
end |
|||
get_local $inPtr0 |
|||
tee_local $inPtr ;; current position in input buffer |
|||
get_local $ilen |
|||
i32.add |
|||
set_local $inPtrEnd |
|||
get_local $outPtr0 ;; start of output buffer |
|||
set_local $outPtr ;; current position in output buffer |
|||
block $noMoreSequence loop ;; iterate through all sequences |
|||
get_local $inPtr |
|||
get_local $inPtrEnd |
|||
i32.ge_u |
|||
br_if $noMoreSequence ;; break when nothing left to read in input buffer |
|||
get_local $inPtr ;; read token -- consume one byte |
|||
i32.load8_u |
|||
get_local $inPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $inPtr |
|||
tee_local $token ;; extract length of literals from token |
|||
i32.const 4 |
|||
i32.shr_u |
|||
tee_local $clen ;; consume extra length bytes if present |
|||
i32.eqz |
|||
if else |
|||
get_local $clen |
|||
i32.const 15 |
|||
i32.eq |
|||
if loop |
|||
get_local $inPtr |
|||
i32.load8_u |
|||
get_local $inPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $inPtr |
|||
tee_local $_ |
|||
get_local $clen |
|||
i32.add |
|||
set_local $clen |
|||
get_local $_ |
|||
i32.const 255 |
|||
i32.eq |
|||
br_if 0 |
|||
end end |
|||
get_local $outPtr ;; copy literals to ouput buffer |
|||
get_local $inPtr |
|||
get_local $clen |
|||
call $copy |
|||
get_local $outPtr ;; advance output buffer pointer past copy |
|||
get_local $clen |
|||
i32.add |
|||
set_local $outPtr |
|||
get_local $clen ;; advance input buffer pointer past literals |
|||
get_local $inPtr |
|||
i32.add |
|||
tee_local $inPtr |
|||
get_local $inPtrEnd ;; exit if this is the last sequence |
|||
i32.eq |
|||
br_if $noMoreSequence |
|||
end |
|||
get_local $outPtr ;; read match offset |
|||
get_local $inPtr |
|||
i32.load8_u |
|||
get_local $inPtr |
|||
i32.load8_u offset=1 |
|||
i32.const 8 |
|||
i32.shl |
|||
i32.or |
|||
i32.sub |
|||
tee_local $matchPtr |
|||
get_local $outPtr ;; match position can't be outside input buffer bounds |
|||
i32.eq |
|||
br_if $noMoreSequence |
|||
get_local $matchPtr |
|||
get_local $inPtrEnd |
|||
i32.lt_u |
|||
br_if $noMoreSequence |
|||
get_local $inPtr ;; advance input pointer past match offset bytes |
|||
i32.const 2 |
|||
i32.add |
|||
set_local $inPtr |
|||
get_local $token ;; extract length of match from token |
|||
i32.const 15 |
|||
i32.and |
|||
i32.const 4 |
|||
i32.add |
|||
tee_local $clen |
|||
i32.const 19 ;; consume extra length bytes if present |
|||
i32.eq |
|||
if loop |
|||
get_local $inPtr |
|||
i32.load8_u |
|||
get_local $inPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $inPtr |
|||
tee_local $_ |
|||
get_local $clen |
|||
i32.add |
|||
set_local $clen |
|||
get_local $_ |
|||
i32.const 255 |
|||
i32.eq |
|||
br_if 0 |
|||
end end |
|||
get_local $outPtr ;; copy match to ouput buffer |
|||
get_local $matchPtr |
|||
get_local $clen |
|||
call $copy |
|||
get_local $clen ;; advance output buffer pointer past copy |
|||
get_local $outPtr |
|||
i32.add |
|||
set_local $outPtr |
|||
br 0 |
|||
end end $noMoreSequence |
|||
get_local $outPtr ;; return number of written bytes |
|||
get_local $outPtr0 |
|||
i32.sub |
|||
) |
|||
|
|||
;; |
|||
;; Private functions |
|||
;; |
|||
|
|||
;; |
|||
;; Encode a sequence token |
|||
;; |
|||
;; Reference documentation: |
|||
;; https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md |
|||
;; |
|||
(func $writeToken |
|||
(param $outPtr i32) |
|||
(param $llen i32) |
|||
(param $mlen i32) |
|||
get_local $outPtr |
|||
get_local $llen |
|||
i32.const 15 |
|||
get_local $llen |
|||
i32.const 15 |
|||
i32.lt_u |
|||
select |
|||
i32.const 4 |
|||
i32.shl |
|||
get_local $mlen |
|||
i32.const 15 |
|||
get_local $mlen |
|||
i32.const 15 |
|||
i32.lt_u |
|||
select |
|||
i32.or |
|||
i32.store8 |
|||
) |
|||
|
|||
;; |
|||
;; Encode and output length bytes. The return value is the pointer following |
|||
;; the last byte written. |
|||
;; |
|||
;; Reference documentation: |
|||
;; https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md |
|||
;; |
|||
(func $writeLength |
|||
(param $outPtr i32) |
|||
(param $len i32) |
|||
(result i32) |
|||
get_local $len |
|||
i32.const 15 |
|||
i32.sub |
|||
set_local $len |
|||
loop |
|||
get_local $outPtr |
|||
get_local $len |
|||
i32.const 255 |
|||
get_local $len |
|||
i32.const 255 |
|||
i32.lt_u |
|||
select |
|||
i32.store8 |
|||
get_local $outPtr |
|||
i32.const 1 |
|||
i32.add |
|||
set_local $outPtr |
|||
get_local $len |
|||
i32.const 255 |
|||
i32.sub |
|||
tee_local $len |
|||
i32.const 0 |
|||
i32.ge_s |
|||
br_if 0 |
|||
end |
|||
get_local $outPtr |
|||
) |
|||
|
|||
;; |
|||
;; Copy n bytes from source to destination. |
|||
;; |
|||
;; It is overlap-safe only from left-to-right -- which is only what is |
|||
;; required in the current module. |
|||
;; |
|||
(func $copy |
|||
(param $dst i32) |
|||
(param $src i32) |
|||
(param $len i32) |
|||
block $lessThan8 loop |
|||
get_local $len |
|||
i32.const 8 |
|||
i32.lt_u |
|||
br_if $lessThan8 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u |
|||
i32.store8 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=1 |
|||
i32.store8 offset=1 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=2 |
|||
i32.store8 offset=2 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=3 |
|||
i32.store8 offset=3 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=4 |
|||
i32.store8 offset=4 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=5 |
|||
i32.store8 offset=5 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=6 |
|||
i32.store8 offset=6 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=7 |
|||
i32.store8 offset=7 |
|||
get_local $dst |
|||
i32.const 8 |
|||
i32.add |
|||
set_local $dst |
|||
get_local $src |
|||
i32.const 8 |
|||
i32.add |
|||
set_local $src |
|||
get_local $len |
|||
i32.const -8 |
|||
i32.add |
|||
set_local $len |
|||
br 0 |
|||
end end $lessThan8 |
|||
get_local $len |
|||
i32.const 4 |
|||
i32.ge_u |
|||
if |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u |
|||
i32.store8 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=1 |
|||
i32.store8 offset=1 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=2 |
|||
i32.store8 offset=2 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=3 |
|||
i32.store8 offset=3 |
|||
get_local $dst |
|||
i32.const 4 |
|||
i32.add |
|||
set_local $dst |
|||
get_local $src |
|||
i32.const 4 |
|||
i32.add |
|||
set_local $src |
|||
get_local $len |
|||
i32.const -4 |
|||
i32.add |
|||
set_local $len |
|||
end |
|||
get_local $len |
|||
i32.const 2 |
|||
i32.ge_u |
|||
if |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u |
|||
i32.store8 |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u offset=1 |
|||
i32.store8 offset=1 |
|||
get_local $dst |
|||
i32.const 2 |
|||
i32.add |
|||
set_local $dst |
|||
get_local $src |
|||
i32.const 2 |
|||
i32.add |
|||
set_local $src |
|||
get_local $len |
|||
i32.const -2 |
|||
i32.add |
|||
set_local $len |
|||
end |
|||
get_local $len |
|||
i32.eqz |
|||
if else |
|||
get_local $dst |
|||
get_local $src |
|||
i32.load8_u |
|||
i32.store8 |
|||
end |
|||
) |
|||
|
|||
;; |
|||
;; module end |
|||
;; |
|||
) |
|||
@ -0,0 +1,328 @@ |
|||
/******************************************************************************* |
|||
|
|||
publicsuffixlist.js - an efficient javascript implementation to deal with |
|||
Mozilla Foundation's Public Suffix List <http://publicsuffix.org/list/>
|
|||
Copyright (C) 2013-2018 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/publicsuffixlist.js */ |
|||
|
|||
/* |
|||
This code is mostly dumb: I consider this to be lower-level code, thus |
|||
in order to ensure efficiency, the caller is responsible for sanitizing |
|||
the inputs. |
|||
*/ |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// A single instance of PublicSuffixList is enough.
|
|||
|
|||
;(function(root) { |
|||
|
|||
'use strict'; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
let exceptions = new Map(); |
|||
let rules = new Map(); |
|||
|
|||
// This value dictate how the search will be performed:
|
|||
// < this.cutoffLength = indexOf()
|
|||
// >= this.cutoffLength = binary search
|
|||
const cutoffLength = 256; |
|||
const mustPunycode = /[^a-z0-9.-]/; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// In the context of this code, a domain is defined as:
|
|||
// "{label}.{public suffix}".
|
|||
// A single standalone label is a public suffix as per
|
|||
// http://publicsuffix.org/list/:
|
|||
// "If no rules match, the prevailing rule is '*' "
|
|||
// This means 'localhost' is not deemed a domain by this
|
|||
// code, since according to the definition above, it would be
|
|||
// evaluated as a public suffix. The caller is therefore responsible to
|
|||
// decide how to further interpret such public suffix.
|
|||
//
|
|||
// `hostname` must be a valid ascii-based hostname.
|
|||
|
|||
function getDomain(hostname) { |
|||
// A hostname starting with a dot is not a valid hostname.
|
|||
if ( !hostname || hostname.charAt(0) === '.' ) { |
|||
return ''; |
|||
} |
|||
hostname = hostname.toLowerCase(); |
|||
var suffix = getPublicSuffix(hostname); |
|||
if ( suffix === hostname ) { |
|||
return ''; |
|||
} |
|||
var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1); |
|||
if ( pos <= 0 ) { |
|||
return hostname; |
|||
} |
|||
return hostname.slice(pos + 1); |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Return longest public suffix.
|
|||
//
|
|||
// `hostname` must be a valid ascii-based string which respect hostname naming.
|
|||
|
|||
function getPublicSuffix(hostname) { |
|||
if ( !hostname ) { |
|||
return ''; |
|||
} |
|||
// Since we slice down the hostname with each pass, the first match
|
|||
// is the longest, so no need to find all the matching rules.
|
|||
var pos; |
|||
while ( true ) { |
|||
pos = hostname.indexOf('.'); |
|||
if ( pos < 0 ) { |
|||
return hostname; |
|||
} |
|||
if ( search(exceptions, hostname) ) { |
|||
return hostname.slice(pos + 1); |
|||
} |
|||
if ( search(rules, hostname) ) { |
|||
return hostname; |
|||
} |
|||
if ( search(rules, '*' + hostname.slice(pos)) ) { |
|||
return hostname; |
|||
} |
|||
hostname = hostname.slice(pos + 1); |
|||
} |
|||
// unreachable
|
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Look up a specific hostname.
|
|||
|
|||
function search(store, hostname) { |
|||
// Extract TLD
|
|||
var pos = hostname.lastIndexOf('.'); |
|||
var tld, remainder; |
|||
if ( pos < 0 ) { |
|||
tld = hostname; |
|||
remainder = hostname; |
|||
} else { |
|||
tld = hostname.slice(pos + 1); |
|||
remainder = hostname.slice(0, pos); |
|||
} |
|||
var substore = store.get(tld); |
|||
if ( substore === undefined ) { return false; } |
|||
// If substore is a string, use indexOf()
|
|||
if ( typeof substore === 'string' ) { |
|||
return substore.indexOf(' ' + remainder + ' ') >= 0; |
|||
} |
|||
// It is an array: use binary search.
|
|||
var l = remainder.length; |
|||
if ( l >= substore.length ) { return false; } |
|||
var haystack = substore[l]; |
|||
if ( haystack.length === 0 ) { return false; } |
|||
var left = 0; |
|||
var right = Math.floor(haystack.length / l + 0.5); |
|||
var i, needle; |
|||
while ( left < right ) { |
|||
i = left + right >> 1; |
|||
needle = haystack.substr( l * i, l ); |
|||
if ( remainder < needle ) { |
|||
right = i; |
|||
} else if ( remainder > needle ) { |
|||
left = i + 1; |
|||
} else { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Parse and set a UTF-8 text-based suffix list. Format is same as found at:
|
|||
// http://publicsuffix.org/list/
|
|||
//
|
|||
// `toAscii` is a converter from unicode to punycode. Required since the
|
|||
// Public Suffix List contains unicode characters.
|
|||
// Suggestion: use <https://github.com/bestiejs/punycode.js> it's quite good.
|
|||
|
|||
function parse(text, toAscii) { |
|||
exceptions = new Map(); |
|||
rules = new Map(); |
|||
|
|||
// http://publicsuffix.org/list/:
|
|||
// "... all rules must be canonicalized in the normal way
|
|||
// for hostnames - lower-case, Punycode ..."
|
|||
text = text.toLowerCase(); |
|||
|
|||
var lineBeg = 0, lineEnd; |
|||
var textEnd = text.length; |
|||
var line, store, pos, tld; |
|||
|
|||
while ( lineBeg < textEnd ) { |
|||
lineEnd = text.indexOf('\n', lineBeg); |
|||
if ( lineEnd < 0 ) { |
|||
lineEnd = text.indexOf('\r', lineBeg); |
|||
if ( lineEnd < 0 ) { |
|||
lineEnd = textEnd; |
|||
} |
|||
} |
|||
line = text.slice(lineBeg, lineEnd).trim(); |
|||
lineBeg = lineEnd + 1; |
|||
|
|||
if ( line.length === 0 ) { |
|||
continue; |
|||
} |
|||
|
|||
// Ignore comments
|
|||
pos = line.indexOf('//'); |
|||
if ( pos >= 0 ) { |
|||
line = line.slice(0, pos); |
|||
} |
|||
|
|||
// Ignore surrounding whitespaces
|
|||
line = line.trim(); |
|||
if ( !line ) { |
|||
continue; |
|||
} |
|||
|
|||
if ( mustPunycode.test(line) ) { |
|||
line = toAscii(line); |
|||
} |
|||
|
|||
// Is this an exception rule?
|
|||
if ( line.charAt(0) === '!' ) { |
|||
store = exceptions; |
|||
line = line.slice(1); |
|||
} else { |
|||
store = rules; |
|||
} |
|||
|
|||
// Extract TLD
|
|||
pos = line.lastIndexOf('.'); |
|||
if ( pos < 0 ) { |
|||
tld = line; |
|||
} else { |
|||
tld = line.slice(pos + 1); |
|||
line = line.slice(0, pos); |
|||
} |
|||
|
|||
// Store suffix using tld as key
|
|||
var substore = store.get(tld); |
|||
if ( substore === undefined ) { |
|||
store.set(tld, (substore = [])); |
|||
} |
|||
if ( line ) { |
|||
substore.push(line); |
|||
} |
|||
} |
|||
crystallize(exceptions); |
|||
crystallize(rules); |
|||
|
|||
window.dispatchEvent(new CustomEvent('publicSuffixList')); |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Cristallize the storage of suffixes using optimal internal representation
|
|||
// for future look up.
|
|||
|
|||
function crystallize(store) { |
|||
for ( var entry of store ) { |
|||
var tld = entry[0]; |
|||
var suffixes = entry[1]; |
|||
// No suffix
|
|||
if ( suffixes.length === 0 ) { |
|||
store.set(tld, ''); |
|||
continue; |
|||
} |
|||
// Concatenated list of suffixes less than cutoff length:
|
|||
// Store as string, lookup using indexOf()
|
|||
var s = suffixes.join(' '); |
|||
if ( s.length < cutoffLength ) { |
|||
store.set(tld, ' ' + s + ' '); |
|||
continue; |
|||
} |
|||
// Concatenated list of suffixes greater or equal to cutoff length
|
|||
// Store as array keyed on suffix length, lookup using binary search.
|
|||
// I borrowed the idea to key on string length here:
|
|||
// http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072
|
|||
var i = suffixes.length, l; |
|||
var aa = []; |
|||
while ( i-- ) { |
|||
var suffix = suffixes[i]; |
|||
var j = aa.length; |
|||
l = suffix.length; |
|||
while ( j <= l ) { |
|||
aa[j] = []; j += 1; |
|||
} |
|||
aa[l].push(suffix); |
|||
} |
|||
l = aa.length; |
|||
while ( l-- ) { |
|||
aa[l] = aa[l].sort().join(''); |
|||
} |
|||
store.set(tld, aa); |
|||
} |
|||
return store; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
const selfieMagic = 1; |
|||
|
|||
function toSelfie() { |
|||
return { |
|||
magic: selfieMagic, |
|||
rules: Array.from(rules), |
|||
exceptions: Array.from(exceptions) |
|||
}; |
|||
} |
|||
|
|||
function fromSelfie(selfie) { |
|||
if ( typeof selfie !== 'object' || selfie.magic !== selfieMagic ) { |
|||
return false; |
|||
} |
|||
rules = new Map(selfie.rules); |
|||
exceptions = new Map(selfie.exceptions); |
|||
window.dispatchEvent(new CustomEvent('publicSuffixList')); |
|||
return true; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Public API
|
|||
|
|||
root = root || window; |
|||
|
|||
root.publicSuffixList = { |
|||
version: '1.0', |
|||
parse: parse, |
|||
getDomain: getDomain, |
|||
getPublicSuffix: getPublicSuffix, |
|||
toSelfie: toSelfie, |
|||
fromSelfie: fromSelfie, |
|||
get empty() { |
|||
return rules.size === 0; |
|||
} |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(this); |
|||
|
|||
@ -0,0 +1,530 @@ |
|||
/*! https://mths.be/punycode v1.3.2 by @mathias */ |
|||
;(function(root) { |
|||
|
|||
/** Detect free variables */ |
|||
var freeExports = typeof exports == 'object' && exports && |
|||
!exports.nodeType && exports; |
|||
var freeModule = typeof module == 'object' && module && |
|||
!module.nodeType && module; |
|||
var freeGlobal = typeof global == 'object' && global; |
|||
if ( |
|||
freeGlobal.global === freeGlobal || |
|||
freeGlobal.window === freeGlobal || |
|||
freeGlobal.self === freeGlobal |
|||
) { |
|||
root = freeGlobal; |
|||
} |
|||
|
|||
/** |
|||
* The `punycode` object. |
|||
* @name punycode |
|||
* @type Object |
|||
*/ |
|||
var punycode, |
|||
|
|||
/** Highest positive signed 32-bit float value */ |
|||
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
|
|||
|
|||
/** Bootstring parameters */ |
|||
base = 36, |
|||
tMin = 1, |
|||
tMax = 26, |
|||
skew = 38, |
|||
damp = 700, |
|||
initialBias = 72, |
|||
initialN = 128, // 0x80
|
|||
delimiter = '-', // '\x2D'
|
|||
|
|||
/** Regular expressions */ |
|||
regexPunycode = /^xn--/, |
|||
regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
|
|||
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
|
|||
|
|||
/** Error messages */ |
|||
errors = { |
|||
'overflow': 'Overflow: input needs wider integers to process', |
|||
'not-basic': 'Illegal input >= 0x80 (not a basic code point)', |
|||
'invalid-input': 'Invalid input' |
|||
}, |
|||
|
|||
/** Convenience shortcuts */ |
|||
baseMinusTMin = base - tMin, |
|||
floor = Math.floor, |
|||
stringFromCharCode = String.fromCharCode, |
|||
|
|||
/** Temporary variable */ |
|||
key; |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
|
|||
/** |
|||
* A generic error utility function. |
|||
* @private |
|||
* @param {String} type The error type. |
|||
* @returns {Error} Throws a `RangeError` with the applicable error message. |
|||
*/ |
|||
function error(type) { |
|||
throw new RangeError(errors[type]); |
|||
} |
|||
|
|||
/** |
|||
* A generic `Array#map` utility function. |
|||
* @private |
|||
* @param {Array} array The array to iterate over. |
|||
* @param {Function} callback The function that gets called for every array |
|||
* item. |
|||
* @returns {Array} A new array of values returned by the callback function. |
|||
*/ |
|||
function map(array, fn) { |
|||
var length = array.length; |
|||
var result = []; |
|||
while (length--) { |
|||
result[length] = fn(array[length]); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* A simple `Array#map`-like wrapper to work with domain name strings or email |
|||
* addresses. |
|||
* @private |
|||
* @param {String} domain The domain name or email address. |
|||
* @param {Function} callback The function that gets called for every |
|||
* character. |
|||
* @returns {Array} A new string of characters returned by the callback |
|||
* function. |
|||
*/ |
|||
function mapDomain(string, fn) { |
|||
var parts = string.split('@'); |
|||
var result = ''; |
|||
if (parts.length > 1) { |
|||
// In email addresses, only the domain name should be punycoded. Leave
|
|||
// the local part (i.e. everything up to `@`) intact.
|
|||
result = parts[0] + '@'; |
|||
string = parts[1]; |
|||
} |
|||
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
|||
string = string.replace(regexSeparators, '\x2E'); |
|||
var labels = string.split('.'); |
|||
var encoded = map(labels, fn).join('.'); |
|||
return result + encoded; |
|||
} |
|||
|
|||
/** |
|||
* Creates an array containing the numeric code points of each Unicode |
|||
* character in the string. While JavaScript uses UCS-2 internally, |
|||
* this function will convert a pair of surrogate halves (each of which |
|||
* UCS-2 exposes as separate characters) into a single code point, |
|||
* matching UTF-16. |
|||
* @see `punycode.ucs2.encode` |
|||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|||
* @memberOf punycode.ucs2 |
|||
* @name decode |
|||
* @param {String} string The Unicode input string (UCS-2). |
|||
* @returns {Array} The new array of code points. |
|||
*/ |
|||
function ucs2decode(string) { |
|||
var output = [], |
|||
counter = 0, |
|||
length = string.length, |
|||
value, |
|||
extra; |
|||
while (counter < length) { |
|||
value = string.charCodeAt(counter++); |
|||
if (value >= 0xD800 && value <= 0xDBFF && counter < length) { |
|||
// high surrogate, and there is a next character
|
|||
extra = string.charCodeAt(counter++); |
|||
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
|||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); |
|||
} else { |
|||
// unmatched surrogate; only append this code unit, in case the next
|
|||
// code unit is the high surrogate of a surrogate pair
|
|||
output.push(value); |
|||
counter--; |
|||
} |
|||
} else { |
|||
output.push(value); |
|||
} |
|||
} |
|||
return output; |
|||
} |
|||
|
|||
/** |
|||
* Creates a string based on an array of numeric code points. |
|||
* @see `punycode.ucs2.decode` |
|||
* @memberOf punycode.ucs2 |
|||
* @name encode |
|||
* @param {Array} codePoints The array of numeric code points. |
|||
* @returns {String} The new Unicode string (UCS-2). |
|||
*/ |
|||
function ucs2encode(array) { |
|||
return map(array, function(value) { |
|||
var output = ''; |
|||
if (value > 0xFFFF) { |
|||
value -= 0x10000; |
|||
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); |
|||
value = 0xDC00 | value & 0x3FF; |
|||
} |
|||
output += stringFromCharCode(value); |
|||
return output; |
|||
}).join(''); |
|||
} |
|||
|
|||
/** |
|||
* Converts a basic code point into a digit/integer. |
|||
* @see `digitToBasic()` |
|||
* @private |
|||
* @param {Number} codePoint The basic numeric code point value. |
|||
* @returns {Number} The numeric value of a basic code point (for use in |
|||
* representing integers) in the range `0` to `base - 1`, or `base` if |
|||
* the code point does not represent a value. |
|||
*/ |
|||
function basicToDigit(codePoint) { |
|||
if (codePoint - 48 < 10) { |
|||
return codePoint - 22; |
|||
} |
|||
if (codePoint - 65 < 26) { |
|||
return codePoint - 65; |
|||
} |
|||
if (codePoint - 97 < 26) { |
|||
return codePoint - 97; |
|||
} |
|||
return base; |
|||
} |
|||
|
|||
/** |
|||
* Converts a digit/integer into a basic code point. |
|||
* @see `basicToDigit()` |
|||
* @private |
|||
* @param {Number} digit The numeric value of a basic code point. |
|||
* @returns {Number} The basic code point whose value (when used for |
|||
* representing integers) is `digit`, which needs to be in the range |
|||
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is |
|||
* used; else, the lowercase form is used. The behavior is undefined |
|||
* if `flag` is non-zero and `digit` has no uppercase form. |
|||
*/ |
|||
function digitToBasic(digit, flag) { |
|||
// 0..25 map to ASCII a..z or A..Z
|
|||
// 26..35 map to ASCII 0..9
|
|||
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); |
|||
} |
|||
|
|||
/** |
|||
* Bias adaptation function as per section 3.4 of RFC 3492. |
|||
* http://tools.ietf.org/html/rfc3492#section-3.4
|
|||
* @private |
|||
*/ |
|||
function adapt(delta, numPoints, firstTime) { |
|||
var k = 0; |
|||
delta = firstTime ? floor(delta / damp) : delta >> 1; |
|||
delta += floor(delta / numPoints); |
|||
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { |
|||
delta = floor(delta / baseMinusTMin); |
|||
} |
|||
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); |
|||
} |
|||
|
|||
/** |
|||
* Converts a Punycode string of ASCII-only symbols to a string of Unicode |
|||
* symbols. |
|||
* @memberOf punycode |
|||
* @param {String} input The Punycode string of ASCII-only symbols. |
|||
* @returns {String} The resulting string of Unicode symbols. |
|||
*/ |
|||
function decode(input) { |
|||
// Don't use UCS-2
|
|||
var output = [], |
|||
inputLength = input.length, |
|||
out, |
|||
i = 0, |
|||
n = initialN, |
|||
bias = initialBias, |
|||
basic, |
|||
j, |
|||
index, |
|||
oldi, |
|||
w, |
|||
k, |
|||
digit, |
|||
t, |
|||
/** Cached calculation results */ |
|||
baseMinusT; |
|||
|
|||
// Handle the basic code points: let `basic` be the number of input code
|
|||
// points before the last delimiter, or `0` if there is none, then copy
|
|||
// the first basic code points to the output.
|
|||
|
|||
basic = input.lastIndexOf(delimiter); |
|||
if (basic < 0) { |
|||
basic = 0; |
|||
} |
|||
|
|||
for (j = 0; j < basic; ++j) { |
|||
// if it's not a basic code point
|
|||
if (input.charCodeAt(j) >= 0x80) { |
|||
error('not-basic'); |
|||
} |
|||
output.push(input.charCodeAt(j)); |
|||
} |
|||
|
|||
// Main decoding loop: start just after the last delimiter if any basic code
|
|||
// points were copied; start at the beginning otherwise.
|
|||
|
|||
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { |
|||
|
|||
// `index` is the index of the next character to be consumed.
|
|||
// Decode a generalized variable-length integer into `delta`,
|
|||
// which gets added to `i`. The overflow checking is easier
|
|||
// if we increase `i` as we go, then subtract off its starting
|
|||
// value at the end to obtain `delta`.
|
|||
for (oldi = i, w = 1, k = base; /* no condition */; k += base) { |
|||
|
|||
if (index >= inputLength) { |
|||
error('invalid-input'); |
|||
} |
|||
|
|||
digit = basicToDigit(input.charCodeAt(index++)); |
|||
|
|||
if (digit >= base || digit > floor((maxInt - i) / w)) { |
|||
error('overflow'); |
|||
} |
|||
|
|||
i += digit * w; |
|||
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); |
|||
|
|||
if (digit < t) { |
|||
break; |
|||
} |
|||
|
|||
baseMinusT = base - t; |
|||
if (w > floor(maxInt / baseMinusT)) { |
|||
error('overflow'); |
|||
} |
|||
|
|||
w *= baseMinusT; |
|||
|
|||
} |
|||
|
|||
out = output.length + 1; |
|||
bias = adapt(i - oldi, out, oldi == 0); |
|||
|
|||
// `i` was supposed to wrap around from `out` to `0`,
|
|||
// incrementing `n` each time, so we'll fix that now:
|
|||
if (floor(i / out) > maxInt - n) { |
|||
error('overflow'); |
|||
} |
|||
|
|||
n += floor(i / out); |
|||
i %= out; |
|||
|
|||
// Insert `n` at position `i` of the output
|
|||
output.splice(i++, 0, n); |
|||
|
|||
} |
|||
|
|||
return ucs2encode(output); |
|||
} |
|||
|
|||
/** |
|||
* Converts a string of Unicode symbols (e.g. a domain name label) to a |
|||
* Punycode string of ASCII-only symbols. |
|||
* @memberOf punycode |
|||
* @param {String} input The string of Unicode symbols. |
|||
* @returns {String} The resulting Punycode string of ASCII-only symbols. |
|||
*/ |
|||
function encode(input) { |
|||
var n, |
|||
delta, |
|||
handledCPCount, |
|||
basicLength, |
|||
bias, |
|||
j, |
|||
m, |
|||
q, |
|||
k, |
|||
t, |
|||
currentValue, |
|||
output = [], |
|||
/** `inputLength` will hold the number of code points in `input`. */ |
|||
inputLength, |
|||
/** Cached calculation results */ |
|||
handledCPCountPlusOne, |
|||
baseMinusT, |
|||
qMinusT; |
|||
|
|||
// Convert the input in UCS-2 to Unicode
|
|||
input = ucs2decode(input); |
|||
|
|||
// Cache the length
|
|||
inputLength = input.length; |
|||
|
|||
// Initialize the state
|
|||
n = initialN; |
|||
delta = 0; |
|||
bias = initialBias; |
|||
|
|||
// Handle the basic code points
|
|||
for (j = 0; j < inputLength; ++j) { |
|||
currentValue = input[j]; |
|||
if (currentValue < 0x80) { |
|||
output.push(stringFromCharCode(currentValue)); |
|||
} |
|||
} |
|||
|
|||
handledCPCount = basicLength = output.length; |
|||
|
|||
// `handledCPCount` is the number of code points that have been handled;
|
|||
// `basicLength` is the number of basic code points.
|
|||
|
|||
// Finish the basic string - if it is not empty - with a delimiter
|
|||
if (basicLength) { |
|||
output.push(delimiter); |
|||
} |
|||
|
|||
// Main encoding loop:
|
|||
while (handledCPCount < inputLength) { |
|||
|
|||
// All non-basic code points < n have been handled already. Find the next
|
|||
// larger one:
|
|||
for (m = maxInt, j = 0; j < inputLength; ++j) { |
|||
currentValue = input[j]; |
|||
if (currentValue >= n && currentValue < m) { |
|||
m = currentValue; |
|||
} |
|||
} |
|||
|
|||
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
|||
// but guard against overflow
|
|||
handledCPCountPlusOne = handledCPCount + 1; |
|||
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { |
|||
error('overflow'); |
|||
} |
|||
|
|||
delta += (m - n) * handledCPCountPlusOne; |
|||
n = m; |
|||
|
|||
for (j = 0; j < inputLength; ++j) { |
|||
currentValue = input[j]; |
|||
|
|||
if (currentValue < n && ++delta > maxInt) { |
|||
error('overflow'); |
|||
} |
|||
|
|||
if (currentValue == n) { |
|||
// Represent delta as a generalized variable-length integer
|
|||
for (q = delta, k = base; /* no condition */; k += base) { |
|||
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); |
|||
if (q < t) { |
|||
break; |
|||
} |
|||
qMinusT = q - t; |
|||
baseMinusT = base - t; |
|||
output.push( |
|||
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) |
|||
); |
|||
q = floor(qMinusT / baseMinusT); |
|||
} |
|||
|
|||
output.push(stringFromCharCode(digitToBasic(q, 0))); |
|||
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); |
|||
delta = 0; |
|||
++handledCPCount; |
|||
} |
|||
} |
|||
|
|||
++delta; |
|||
++n; |
|||
|
|||
} |
|||
return output.join(''); |
|||
} |
|||
|
|||
/** |
|||
* Converts a Punycode string representing a domain name or an email address |
|||
* to Unicode. Only the Punycoded parts of the input will be converted, i.e. |
|||
* it doesn't matter if you call it on a string that has already been |
|||
* converted to Unicode. |
|||
* @memberOf punycode |
|||
* @param {String} input The Punycoded domain name or email address to |
|||
* convert to Unicode. |
|||
* @returns {String} The Unicode representation of the given Punycode |
|||
* string. |
|||
*/ |
|||
function toUnicode(input) { |
|||
return mapDomain(input, function(string) { |
|||
return regexPunycode.test(string) |
|||
? decode(string.slice(4).toLowerCase()) |
|||
: string; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Converts a Unicode string representing a domain name or an email address to |
|||
* Punycode. Only the non-ASCII parts of the domain name will be converted, |
|||
* i.e. it doesn't matter if you call it with a domain that's already in |
|||
* ASCII. |
|||
* @memberOf punycode |
|||
* @param {String} input The domain name or email address to convert, as a |
|||
* Unicode string. |
|||
* @returns {String} The Punycode representation of the given domain name or |
|||
* email address. |
|||
*/ |
|||
function toASCII(input) { |
|||
return mapDomain(input, function(string) { |
|||
return regexNonASCII.test(string) |
|||
? 'xn--' + encode(string) |
|||
: string; |
|||
}); |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
|
|||
/** Define the public API */ |
|||
punycode = { |
|||
/** |
|||
* A string representing the current Punycode.js version number. |
|||
* @memberOf punycode |
|||
* @type String |
|||
*/ |
|||
'version': '1.3.2', |
|||
/** |
|||
* An object of methods to convert from JavaScript's internal character |
|||
* representation (UCS-2) to Unicode code points, and back. |
|||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|||
* @memberOf punycode |
|||
* @type Object |
|||
*/ |
|||
'ucs2': { |
|||
'decode': ucs2decode, |
|||
'encode': ucs2encode |
|||
}, |
|||
'decode': decode, |
|||
'encode': encode, |
|||
'toASCII': toASCII, |
|||
'toUnicode': toUnicode |
|||
}; |
|||
|
|||
/** Expose `punycode` */ |
|||
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
|||
// like the following:
|
|||
if ( |
|||
typeof define == 'function' && |
|||
typeof define.amd == 'object' && |
|||
define.amd |
|||
) { |
|||
define('punycode', function() { |
|||
return punycode; |
|||
}); |
|||
} else if (freeExports && freeModule) { |
|||
if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
|
|||
freeModule.exports = punycode; |
|||
} else { // in Narwhal or RingoJS v0.7.0-
|
|||
for (key in punycode) { |
|||
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); |
|||
} |
|||
} |
|||
} else { // in Rhino or a web browser
|
|||
root.punycode = punycode; |
|||
} |
|||
|
|||
}(this)); |
|||
@ -0,0 +1,204 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=560, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" href="css/fa-icons.css" type="text/css"> |
|||
<link rel="stylesheet" type="text/css" href="css/logger-ui.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/logger-ui-inspector.css"> |
|||
<link rel="shortcut icon" type="image/png" href="img/icon_16.png"> |
|||
<title data-i18n="statsPageName"></title> |
|||
<style id="vwRendererRuntimeStyles"></style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div class="permatoolbar"> |
|||
<div> |
|||
<select id="pageSelector"> |
|||
<option value="0" data-i18n="logAll"> |
|||
<option value="-1" data-i18n="logBehindTheScene"> |
|||
<option value="_" data-i18n="loggerCurrentTab"> |
|||
</select> |
|||
<span id="refresh" class="button fa-icon disabled needdom" data-i18n-title="loggerReloadTip">refresh</span> |
|||
<span id="showdom" class="button fa-icon disabled needdom" data-i18n-title="loggerDomInspectorTip">code</span> |
|||
<span id="showpopup" class="button ubo-icon disabled needdom" data-i18n-title="loggerPopupPanelTip"><svg><use href="/img/ublock-defs.svg#ubo-solid"></use></svg></span> |
|||
</div> |
|||
<div> |
|||
<a id="info" class="button fa-icon" href="https://github.com/gorhill/uBlock/wiki/The-logger" target="_blank" data-i18n-title="loggerInfoTip">info-circle</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="inspectors"> |
|||
<div id="domInspector" class="inspector hCompact"> |
|||
<div class="permatoolbar"> |
|||
<div> |
|||
<span class="button fa-icon vCompactToggler">double-angle-up</span> |
|||
<span class="button fa-icon hCompactToggler">double-angle-left</span> |
|||
<!-- <span class="button fa highlightMode" style="display: none"></span> --> |
|||
<span class="button fa-icon revert disabled">eraser</span> |
|||
<span class="button fa-icon commit disabled">floppy-o</span> |
|||
</div> |
|||
</div> |
|||
<div class="vscrollable"> |
|||
<ul id="domTree"></ul> |
|||
</div> |
|||
</div> |
|||
<div id="netInspector" class="inspector f"> |
|||
<div class="permatoolbar"> |
|||
<div> |
|||
<span class="button fa-icon vCompactToggler">double-angle-up</span> |
|||
<span id="clean" class="button fa-icon disabled">times</span> |
|||
<span id="clear" class="button fa-icon disabled" data-i18n-title="loggerClearTip">eraser</span> |
|||
<span id="pause"><span class="button fa-icon" data-i18n-title="loggerPauseTip">pause-circle-o</span><span class="button fa-icon" data-i18n-title="loggerUnpauseTip">play-circle-o</span></span> |
|||
<span id="filterExprGroup"> |
|||
<span id="filterButton" class="button fa-icon" data-i18n-title="loggerRowFiltererButtonTip">filter</span> |
|||
<span id="filterInput"> |
|||
<input type="text" placeholder="logFilterPrompt"> |
|||
<span id="filterExprButton" class="button fa-icon expanded" data-i18n-title="loggerRowFiltererBuiltinTip">angle-up</span> |
|||
<div id="filterExprPicker"> |
|||
<div><span data-filtex="!" data-i18n="loggerRowFiltererBuiltinNot"></span><span data-filtex="\t--\t|\t<<\t|\t##" data-i18n="loggerRowFiltererBuiltinBlocked"></span><span data-filtex="\t\+\+\t|\t\*\*\t|\t#@#" data-i18n="loggerRowFiltererBuiltinAllowed"></span></div> |
|||
<div><span data-filtex="!" data-i18n="loggerRowFiltererBuiltinNot"></span><span data-filtex="\t(?:css|font)\t">css/font</span><span data-filtex="\timage\t">image</span><span data-filtex="\t(?:inline-)?script(?:ing)?\t">script</span><span data-filtex="\t(?:websocket|xhr)\t">xhr</span><span data-filtex="\tframe\t">frame</span><span data-filtex="\tdom\t">dom</span></div> |
|||
<div><span data-filtex="!" data-i18n="loggerRowFiltererBuiltinNot"></span><span data-filtex="\t(?:0,)?1\t" data-i18n="loggerRowFiltererBuiltin1p"></span><span data-filtex="\t(?:3(?:,\d)?|0,3)\t" data-i18n="loggerRowFiltererBuiltin3p"></span></div> |
|||
</div> |
|||
</span> |
|||
</span> |
|||
</div> |
|||
<div> |
|||
<span id="loggerExport" class="button fa-icon">clipboard</span> |
|||
<span id="settings" class="button fa-icon">cog</span> |
|||
</div> |
|||
</div> |
|||
<div class="vscrollable"> |
|||
<div id="vwRenderer"> |
|||
<div id="vwScroller"> |
|||
<div id="vwVirtualContent"> |
|||
<div id="vwContent"></div> |
|||
</div> |
|||
</div> |
|||
<div id="vwLineSizer"> |
|||
<div class="logEntry oneLine"><div><span>00:00:00</span><span> </span><span>**</span><span> </span><span>3,3</span><span>inline-script</span><span> </span></div></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<iframe id="popupContainer"></iframe> |
|||
</div> |
|||
|
|||
<div id="modalOverlay"> |
|||
<div> |
|||
<div id="modalOverlayContainer"></div> |
|||
<div id="modalOverlayClose"><svg viewBox="0 0 64 64"><path d="M 16 16 L 48 48 M 16 48 L 48 16" /></svg></div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="templates" style="display: none;"> |
|||
<div id="logEntryTemplate"><div><span></span>​<span></span>​<span></span>​<span></span>​<span></span>​<span></span>​<span></span></div></div> |
|||
<div id="renderedURLTemplate"><span><span></span><b></b><span></span></span></div> |
|||
|
|||
<div id="netFilteringDialog" data-pane="details"> |
|||
<div class="hide preview"><span>click to preview</span></div> |
|||
<div class="headers"> |
|||
  |
|||
<span class="header details" data-pane="details" data-i18n="loggerEntryDetailsHeader"></span> |
|||
<span class="header dynamic" data-pane="dynamic" data-i18n="loggerURLFilteringHeader"></span> |
|||
<span class="header static" data-pane="static" data-i18n="loggerStaticFilteringHeader"></span> |
|||
<span class="tools"><span class="fa-icon reload">refresh</span> <span class="fa-icon picker">eye-dropper</span></span> |
|||
</div> |
|||
<div class="panes"> |
|||
<div class="pane details" data-pane="details"> |
|||
<div><span data-i18n="loggerEntryDetailsFilter"></span><span></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsFilterList"></span><span class="prose"></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsRule"></span><span></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsRootContext"></span><span></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsContext"></span><span></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsPartyness"></span><span class="prose"></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsType"></span><span></span></div> |
|||
<div><span data-i18n="loggerEntryDetailsURL"></span><span></span></div> |
|||
</div> |
|||
<div class="pane dynamic" data-pane="dynamic"> |
|||
<div class="toolbar row"> |
|||
<span><span id="saveRules" class="fa-icon">lock</span></span> |
|||
<span> |
|||
<label><span data-i18n="loggerURLFilteringContextLabel"></span> <select class="dynamic origin"></select></label>  |
|||
<label><span data-i18n="loggerURLFilteringTypeLabel"></span> <select class="dynamic type"><option><option value="*">*</select></label> |
|||
</span> |
|||
<div class="entry row"> |
|||
<span class="action"><span class="allow"> </span><span class="noop"> </span><span class="block"> </span></span> |
|||
<span class="url"></span> |
|||
</div> |
|||
</div> |
|||
<div class="entries"></div> |
|||
</div> |
|||
<div class="pane static" data-pane="static"> |
|||
<div></div> |
|||
<div><textarea class="staticFilter" spellcheck="false" value=""></textarea> |
|||
<button id="createStaticFilter" class="custom important" type="button" data-i18n="pickerCreate"></button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="filterFinderDialog"> |
|||
</div> |
|||
|
|||
<div id="filterFinderListEntry"> |
|||
<span><!-- |
|||
--><a href="asset-viewer.html?url=" target="_blank"></a> <!-- |
|||
--><a href="" class="fa-icon" target="_blank">home</a><!-- |
|||
--></span> |
|||
</div> |
|||
|
|||
<div id="cosmeticFilteringDialog" class="modalDialog"> |
|||
<textarea class="cosmeticFilters" value=""></textarea> |
|||
<button id="createCosmeticFilters" class="custom important" type="button" data-i18n="pickerCreate"></button> |
|||
</div> |
|||
|
|||
<div id="loggerSettingsDialog"> |
|||
<div><span data-i18n="loggerSettingDiscardPrompt"></span> |
|||
<ul> |
|||
<li><label data-i18n="loggerSettingPerEntryMaxAge"><input type="number" min="0" max="50000" /></label> |
|||
<li><label data-i18n="loggerSettingPerTabMaxLoads"><input type="number" min="0" max="1000000" /></label> |
|||
<li><label data-i18n="loggerSettingPerTabMaxEntries"><input type="number" min="0" max="1000000" /></label> |
|||
</ul> |
|||
</div> |
|||
<div><span data-i18n="loggerSettingHideColumnsPrompt"></span> |
|||
<ul> |
|||
<li><label data-i18n="loggerSettingHideColumnTime"><input type="checkbox" data-column="0" /></label> |
|||
<li><label data-i18n="loggerSettingHideColumnFilter"><input type="checkbox" data-column="1" /></label> |
|||
<li><label data-i18n="loggerSettingHideColumnContext"><input type="checkbox" data-column="3" /></label> |
|||
<li><label data-i18n="loggerSettingHideColumnPartyness"><input type="checkbox" data-column="4" /></label> |
|||
</ul> |
|||
</div> |
|||
<div><label data-i18n="loggerSettingPerEntryLineCount"><input type="number" min="2" max="6"></label></div> |
|||
</div> |
|||
|
|||
<div id="loggerExportDialog"> |
|||
<div class="options"> |
|||
<div data-radio="format"> |
|||
<span data-i18n="loggerExportFormatList" data-radio-item="list"></span> |
|||
<span data-i18n="loggerExportFormatTable" data-radio-item="table"></span> |
|||
</div> |
|||
<div data-radio="encoding"> |
|||
<span data-i18n="loggerExportEncodePlain" data-radio-item="plain"></span> |
|||
<span data-i18n="loggerExportEncodeMarkdown" data-radio-item="markdown"></span> |
|||
</div> |
|||
<div> |
|||
<span data-i18n="genericCopyToClipboard" class="pushbutton"></span> |
|||
</div> |
|||
</div> |
|||
<textarea class="output" readonly spellcheck="false"></textarea> |
|||
</div> |
|||
</div> |
|||
|
|||
<script src="js/fa-icons.js"></script> |
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/logger-ui.js"></script> |
|||
<script src="js/logger-ui-inspector.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,75 @@ |
|||
<!DOCTYPE html> |
|||
<html id="uBO-popup-panel"> |
|||
|
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" href="css/common.css" type="text/css"> |
|||
<link rel="stylesheet" href="css/fa-icons.css" type="text/css"> |
|||
<link rel="stylesheet" href="css/popup.css" type="text/css"> |
|||
<link rel="stylesheet" href="css/vapi-popup.css" type="text/css"><!-- Optional platform-specific CSS rules --> |
|||
<title>uBlock Origin</title> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="appinfo"><span id="appname"> </span> <span id="version"> </span></div> |
|||
<div id="panes"> |
|||
<div class="tooltipContainer"> |
|||
<p id="switch" role="button" aria-label data-tip-position="under" tabindex="0"><span class="fa-icon">power-off</span></p> |
|||
<p id="basicTools"> |
|||
<span id="gotoZap" class="fa-icon tool" data-i18n-tip="popupTipZapper" data-tip-position="under">bolt</span> |
|||
<span id="gotoPick" class="fa-icon tool" data-i18n-tip="popupTipPicker" data-tip-position="under">eye-dropper</span> |
|||
<a href="logger-ui.html#_" class="fa-icon tool enabled" aria-label="data-tip" data-i18n-tip="popupTipLog" data-tip-position="under" target="uBOLogger" tabindex="0">list-alt</a> |
|||
<a href="dashboard.html" class="fa-icon tool enabled" aria-label="data-tip" data-i18n-tip="popupTipDashboard" data-tip-position="under" target="uBODashboard" tabindex="0">sliders</a> |
|||
</p> |
|||
<h2 id="dfToggler" data-i18n="popupBlockedRequestPrompt"> </h2> |
|||
<p class="statName"> |
|||
<span data-i18n="popupBlockedOnThisPagePrompt"> </span> |
|||
</p> |
|||
<p class="statValue" id="page-blocked">?</p> |
|||
<div id="refresh" class="fa-icon">refresh</div> |
|||
<p class="statName"> |
|||
<span data-i18n="popupBlockedSinceInstallPrompt"> </span> |
|||
</p> |
|||
<p class="statValue" id="total-blocked">?</p> |
|||
<h2 data-i18n="popupHitDomainCountPrompt"> </h2> |
|||
<p class="statValue" id="popupHitDomainCount"> </p> |
|||
<div id="extraTools"> |
|||
<span id="no-popups" class="hnSwitch fa-icon fa-icon-badged" role="button" aria-label tabindex="0">files-o<svg class="nope" viewBox="0 0 20 20"><path d="M1,1 19,19M1,19 19,1" /></svg></span> |
|||
<span id="no-large-media" class="hnSwitch fa-icon fa-icon-badged" role="button" aria-label tabindex="0">film<svg class="nope" viewBox="0 0 20 20"><path d="M1,1 19,19M1,19 19,1" /></svg></span> |
|||
<span id="no-cosmetic-filtering" class="hnSwitch fa-icon fa-icon-badged" role="button" aria-label tabindex="0">eye-slash<svg class="nope" viewBox="0 0 20 20"><path d="M1,1 19,19M1,19 19,1" /></svg></span> |
|||
<span id="no-remote-fonts" class="hnSwitch fa-icon fa-icon-badged" role="button" aria-label tabindex="0">font<svg class="nope" viewBox="0 0 20 20"><path d="M1,1 19,19M1,19 19,1" /></svg></span> |
|||
<span id="no-scripting" class="hnSwitch fa-icon fa-icon-badged" role="button" aria-label tabindex="0">code<svg class="nope" viewBox="0 0 20 20"><path d="M1,1 19,19M1,19 19,1" /></svg></span> |
|||
</div> |
|||
</div><!-- DO NOT REMOVE --><div class="tooltipContainer"> |
|||
<div id="firewallContainer" class="minimized"> |
|||
<div data-des="*" data-type="*"><span data-i18n="popupAnyRulePrompt"></span><span data-src="/" data-i18n-tip="popupTipGlobalRules" data-tip-position="under"> </span><span data-src="." data-i18n-tip="popupTipLocalRules" data-tip-position="under"> </span></div> |
|||
<div data-des="*" data-type="image"><span data-i18n="popupImageRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
<div data-des="*" data-type="3p"><span data-i18n="popup3pAnyRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
<div data-des="*" data-type="inline-script"><span data-i18n="popupInlineScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
<div data-des="*" data-type="1p-script"><span data-i18n="popup1pScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
<div data-des="*" data-type="3p-script"><span data-i18n="popup3pScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
<div data-des="*" data-type="3p-frame"><span data-i18n="popup3pFrameRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> |
|||
</div><div id="rulesetTools"><span id="saveRules" class="fa-icon" data-i18n-tip="popupTipSaveRules" data-tip-position="under">lock</span><span id="revertRules" class="fa-icon" data-i18n-tip="popupTipRevertRules" data-tip-position="under">eraser</span></div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="templates" style="display: none"> |
|||
<div data-des="" data-type="*"><span><sup></sup><span></span></span><span data-src="/"></span><span data-src="."></span><span data-src="."></span></div> |
|||
<div id="actionSelector"><span id="dynaAllow"></span><span id="dynaNoop"></span><span id="dynaBlock"></span></div> |
|||
<div id="hotspotTip"></div> |
|||
<div id="tooltip"></div> |
|||
</div> |
|||
|
|||
<script src="js/fa-icons.js"></script> |
|||
<script src="lib/punycode.js"></script> |
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/popup.js"></script> |
|||
|
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,71 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — Settings</title> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/settings.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
<div class="body"> |
|||
<ul id="userSettings"> |
|||
<li><input id="collapse-blocked" type="checkbox" data-setting-name="collapseBlocked" data-setting-type="bool"><label data-i18n="settingsCollapseBlockedPrompt" for="collapse-blocked"></label> |
|||
<li><input id="icon-badge" type="checkbox" data-setting-name="showIconBadge" data-setting-type="bool"><label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label> |
|||
<li><input id="context-menu-enabled" type="checkbox" data-setting-name="contextMenuEnabled" data-setting-type="bool"><label data-i18n="settingsContextMenuPrompt" for="context-menu-enabled"></label> |
|||
<li><input id="tooltips-disabled" type="checkbox" data-setting-name="tooltipsDisabled" data-setting-type="bool"><label data-i18n="settingsTooltipsPrompt" for="tooltips-disabled"></label> |
|||
<li><input id="color-blind-friendly" type="checkbox" data-setting-name="colorBlindFriendly" data-setting-type="bool"><label data-i18n="settingsColorBlindPrompt" for="color-blind-friendly"></label> |
|||
<li><input id="cloud-storage-enabled" type="checkbox" data-setting-name="cloudStorageEnabled" data-setting-type="bool"><label data-i18n="settingsCloudStorageEnabledPrompt" for="cloud-storage-enabled"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Cloud-storage" target="_blank"></a> |
|||
<li><input id="advanced-user-enabled" type="checkbox" data-setting-name="advancedUserEnabled" data-setting-type="bool"><label data-i18n="settingsAdvancedUserPrompt" for="advanced-user-enabled"></label> <a class="fa info" href="advanced-settings.html" data-i18n-title="settingsAdvancedUserSettings"></a> |
|||
<li class="subgroup"><span data-i18n="3pGroupPrivacy"></span><ul> |
|||
<li><input id="prefetching-disabled" type="checkbox" data-setting-name="prefetchingDisabled" data-setting-type="bool"><label data-i18n="settingsPrefetchingDisabledPrompt" for="prefetching-disabled"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Dashboard:-Settings#disable-pre-fetching" target="_blank"></a> |
|||
<li><input id="hyperlink-auditing-disabled" type="checkbox" data-setting-name="hyperlinkAuditingDisabled" data-setting-type="bool"><label data-i18n="settingsHyperlinkAuditingDisabledPrompt" for="hyperlink-auditing-disabled"></label> <a class="fa info important" href="https://github.com/gorhill/uBlock/wiki/Dashboard:-Settings#disable-hyperlink-auditing" target="_blank"></a> |
|||
<li><input id="webrtc-ipaddress-hidden" type="checkbox" data-setting-name="webrtcIPAddressHidden" data-setting-type="bool"><label data-i18n="settingsWebRTCIPAddressHiddenPrompt" for="webrtc-ipaddress-hidden"></label> <a class="fa info important" href="https://github.com/gorhill/uBlock/wiki/Prevent-WebRTC-from-leaking-local-IP-address" target="_blank"></a> |
|||
<li><input id="no-csp-reports" type="checkbox" data-setting-name="noCSPReports" data-setting-type="bool"><label data-i18n="settingsNoCSPReportsPrompt" for="no-csp-reports"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Dashboard:-Settings#block-csp-reports" target="_blank"></a> |
|||
</ul> |
|||
<li class="subgroup"><span data-i18n="settingPerSiteSwitchGroup"></span><ul> |
|||
<li><label class="synopsis"><span data-i18n="settingPerSiteSwitchGroupSynopsis"></span> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches" target="_blank"></a></label> |
|||
<li><input id="no-cosmetic-filtering" type="checkbox" data-setting-name="noCosmeticFiltering" data-setting-type="bool"><label data-i18n="settingsNoCosmeticFilteringPrompt" for="no-cosmetic-filtering"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-cosmetic-filtering" target="_blank"></a> |
|||
<li><input id="no-large-media" type="checkbox" data-setting-name="noLargeMedia" data-setting-type="bool"><label data-i18n="settingsNoLargeMediaPrompt" for="no-large-media"><input type="number" min="0"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-large-media-elements" target="_blank"></a> |
|||
<li><input id="no-remote-fonts" type="checkbox" data-setting-name="noRemoteFonts" data-setting-type="bool"><label data-i18n="settingsNoRemoteFontsPrompt" for="no-remote-fonts"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-remote-fonts" target="_blank"></a> |
|||
<li><input id="no-scripting" type="checkbox" data-setting-name="noScripting" data-setting-type="bool"><label data-i18n="settingsNoScriptingPrompt" for="no-scripting"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-scripting" target="_blank"></a> |
|||
</ul> |
|||
</ul> |
|||
|
|||
<div id="localData" style="margin: 0 1em;"> |
|||
<div style="margin: 2.5em 0; border-top: 1px solid #ccc;"></div> |
|||
<ul> |
|||
<li> |
|||
<li style="display: none;"><span data-i18n="settingsLastBackupPrompt"></span><ul> |
|||
<li> |
|||
</ul> |
|||
<li style="display: none;"><span data-i18n="settingsLastRestorePrompt"></span><ul> |
|||
<li> |
|||
<li> |
|||
</ul> |
|||
</ul> |
|||
</div> |
|||
|
|||
<div style="margin: 2.5em 1em;"> |
|||
<p><button class="custom" type="button" id="export" data-i18n="aboutBackupDataButton"></button>  |
|||
<button class="custom" type="button" id="import" data-i18n="aboutRestoreDataButton"></button> |
|||
<p><button class="custom" type="button" id="reset" data-i18n="aboutResetDataButton"></button> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="hidden"> |
|||
<input id="restoreFilePicker" type="file" accept="text/plain"> |
|||
</div> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/settings.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,37 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock Origin — Keyboard shortcuts</title> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/shortcuts.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
<table class="commandEntries"><tbody></tbody></table> |
|||
</div> |
|||
|
|||
<div id="templates" style="display: none;"> |
|||
<table> |
|||
<tr class="commandEntry"> |
|||
<td class="commandDesc"> |
|||
<td class="commandShortcut"> |
|||
<input type="text" placeholder="shortcutCapturePlaceholder"> |
|||
<span class="commandReset">×</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/shortcuts.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,59 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>uBlock — Whitelist</title> |
|||
|
|||
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css"> |
|||
<link rel="stylesheet" href="lib/codemirror/addon/search/matchesonscrollbar.css"> |
|||
|
|||
<link rel="stylesheet" href="css/common.css"> |
|||
<link rel="stylesheet" href="css/dashboard-common.css"> |
|||
<link rel="stylesheet" href="css/cloud-ui.css"> |
|||
<link rel="stylesheet" href="css/whitelist.css"> |
|||
<link rel="stylesheet" href="css/codemirror.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="body"> |
|||
<div id="cloudWidget" class="hide" data-cloud-entry="whitelistPane"></div> |
|||
|
|||
<p class="vverbose"><span data-i18n="whitelistPrompt"></span> <a class="fa info important" href="https://github.com/gorhill/uBlock/wiki/Dashboard:-Whitelist"></a> |
|||
</p> |
|||
<p> |
|||
<button id="whitelistApply" class="custom important iconifiable" type="button" disabled><span class="fa"></span><span data-i18n="whitelistApply"></span></button> |
|||
<button id="whitelistRevert" class="custom iconifiable" type="button" disabled><span class="fa"></span><span data-i18n="genericRevert"></span></button> |
|||
   |
|||
<button id="importWhitelistFromFile" class="custom iconifiable" type="button"><span class="fa"></span><span data-i18n="whitelistImport"></span></button> |
|||
<button id="exportWhitelistToFile" class="custom iconifiable" type="button"><span class="fa"></span><span data-i18n="whitelistExport"></span></button> |
|||
</p> |
|||
</div> |
|||
<div id="whitelist" class="codeMirrorContainer codeMirrorFillVertical"></div> |
|||
|
|||
<div class="hidden"> |
|||
<input id="importFilePicker" type="file" accept="text/plain"> |
|||
</div> |
|||
|
|||
<script src="lib/codemirror/lib/codemirror.js"></script> |
|||
<script src="lib/codemirror/addon/display/panel.js"></script> |
|||
<script src="lib/codemirror/addon/scroll/annotatescrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/matchesonscrollbar.js"></script> |
|||
<script src="lib/codemirror/addon/search/searchcursor.js"></script> |
|||
<script src="lib/codemirror/addon/selection/active-line.js"></script> |
|||
<script src="lib/punycode.js"></script> |
|||
|
|||
<script src="js/codemirror/search.js"></script> |
|||
|
|||
<script src="js/vapi.js"></script> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/dashboard-common.js"></script> |
|||
<script src="js/cloud-ui.js"></script> |
|||
<script src="js/whitelist.js"></script> |
|||
|
|||
</body> |
|||
</html> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue