├── .editorconfig ├── logo.jpg ├── screen.png ├── media ├── ubiquity.webm └── command-editor.png ├── res ├── icons │ ├── bing.png │ ├── bitly.png │ ├── debug.png │ ├── email.png │ ├── help.png │ ├── imdb.png │ ├── print.gif │ ├── collapse.png │ ├── download.png │ ├── encoding.png │ ├── execute.png │ ├── expand.png │ ├── feedly.png │ ├── google.png │ ├── history.ico │ ├── homepage.png │ ├── icon-128.png │ ├── icon-24.png │ ├── icon-32.png │ ├── icon-64.png │ ├── invert.png │ ├── isdown.ico │ ├── libgen.ico │ ├── lingvo.png │ ├── scihub.ico │ ├── settings.png │ ├── spacer.png │ ├── tab_go.png │ ├── upload.png │ ├── youtube.png │ ├── calculator.png │ ├── list_table.png │ ├── resurrect.gif │ ├── tab_delete.png │ ├── wikipedia.ico │ ├── arrow_refresh.png │ ├── forget-email.png │ ├── plugin_edit.png │ ├── document_create.png │ ├── document_delete.png │ ├── translate_bing.ico │ ├── translate_google.ico │ ├── ubiquibot-square.png │ ├── scrapyard.svg │ ├── globe.svg │ └── folder.svg ├── images │ ├── preview.jpg │ └── say-hello.png ├── edit.css ├── cmenu.html ├── commands.html ├── cmenu.js ├── options.html ├── edit.html ├── options.js ├── commands.js └── options.css ├── commands ├── more │ ├── jav.png │ ├── kpop.png │ ├── nyaa.png │ ├── dark-flow.png │ ├── sukebei.png │ ├── whiskas.png │ ├── fontawesome.woff2 │ ├── fontawesome.css │ ├── dark-flow.js │ ├── kpop.js │ └── javlib.js ├── feedsub.js ├── resurrect.js ├── translate.js └── mail.js ├── marketing └── chrome-screen.png ├── .gitignore ├── _config.yml ├── parser ├── contextutils.js ├── suggestion_memory2.js ├── suggestion_memory3.js └── nounutils.js ├── updates.json ├── lib ├── ace │ ├── ext-error_marker.js │ ├── ext-linking.js │ ├── ext-statusbar.js │ ├── ext-spellcheck.js │ ├── ext-themelist.js │ ├── ext-rtl.js │ ├── theme-monokai.js │ ├── ext-whitespace.js │ ├── ext-split.js │ ├── ext-static_highlight.js │ ├── ext-elastic_tabstops_lite.js │ ├── ext-beautify.js │ ├── ext-keybinding_menu.js │ ├── ext-modelist.js │ ├── ext-textarea.js │ ├── ext-searchbox.js │ └── ext-options.js ├── jquery.toc.min.js ├── uuid.js └── jsstore.min.js ├── makefile ├── core.js ├── selection.js ├── popup.html ├── changelog.md ├── manifest.json ├── popup.css ├── README.md ├── background.js └── _layouts └── default.html /.editorconfig: -------------------------------------------------------------------------------- 1 | [makefile] 2 | indent_style = tab -------------------------------------------------------------------------------- /logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/logo.jpg -------------------------------------------------------------------------------- /screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/screen.png -------------------------------------------------------------------------------- /media/ubiquity.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/media/ubiquity.webm -------------------------------------------------------------------------------- /res/icons/bing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/bing.png -------------------------------------------------------------------------------- /res/icons/bitly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/bitly.png -------------------------------------------------------------------------------- /res/icons/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/debug.png -------------------------------------------------------------------------------- /res/icons/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/email.png -------------------------------------------------------------------------------- /res/icons/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/help.png -------------------------------------------------------------------------------- /res/icons/imdb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/imdb.png -------------------------------------------------------------------------------- /res/icons/print.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/print.gif -------------------------------------------------------------------------------- /commands/more/jav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/jav.png -------------------------------------------------------------------------------- /commands/more/kpop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/kpop.png -------------------------------------------------------------------------------- /commands/more/nyaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/nyaa.png -------------------------------------------------------------------------------- /res/icons/collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/collapse.png -------------------------------------------------------------------------------- /res/icons/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/download.png -------------------------------------------------------------------------------- /res/icons/encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/encoding.png -------------------------------------------------------------------------------- /res/icons/execute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/execute.png -------------------------------------------------------------------------------- /res/icons/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/expand.png -------------------------------------------------------------------------------- /res/icons/feedly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/feedly.png -------------------------------------------------------------------------------- /res/icons/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/google.png -------------------------------------------------------------------------------- /res/icons/history.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/history.ico -------------------------------------------------------------------------------- /res/icons/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/homepage.png -------------------------------------------------------------------------------- /res/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/icon-128.png -------------------------------------------------------------------------------- /res/icons/icon-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/icon-24.png -------------------------------------------------------------------------------- /res/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/icon-32.png -------------------------------------------------------------------------------- /res/icons/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/icon-64.png -------------------------------------------------------------------------------- /res/icons/invert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/invert.png -------------------------------------------------------------------------------- /res/icons/isdown.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/isdown.ico -------------------------------------------------------------------------------- /res/icons/libgen.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/libgen.ico -------------------------------------------------------------------------------- /res/icons/lingvo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/lingvo.png -------------------------------------------------------------------------------- /res/icons/scihub.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/scihub.ico -------------------------------------------------------------------------------- /res/icons/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/settings.png -------------------------------------------------------------------------------- /res/icons/spacer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/spacer.png -------------------------------------------------------------------------------- /res/icons/tab_go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/tab_go.png -------------------------------------------------------------------------------- /res/icons/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/upload.png -------------------------------------------------------------------------------- /res/icons/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/youtube.png -------------------------------------------------------------------------------- /res/images/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/images/preview.jpg -------------------------------------------------------------------------------- /media/command-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/media/command-editor.png -------------------------------------------------------------------------------- /res/icons/calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/calculator.png -------------------------------------------------------------------------------- /res/icons/list_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/list_table.png -------------------------------------------------------------------------------- /res/icons/resurrect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/resurrect.gif -------------------------------------------------------------------------------- /res/icons/tab_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/tab_delete.png -------------------------------------------------------------------------------- /res/icons/wikipedia.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/wikipedia.ico -------------------------------------------------------------------------------- /res/images/say-hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/images/say-hello.png -------------------------------------------------------------------------------- /commands/more/dark-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/dark-flow.png -------------------------------------------------------------------------------- /commands/more/sukebei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/sukebei.png -------------------------------------------------------------------------------- /commands/more/whiskas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/whiskas.png -------------------------------------------------------------------------------- /marketing/chrome-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/marketing/chrome-screen.png -------------------------------------------------------------------------------- /res/icons/arrow_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/arrow_refresh.png -------------------------------------------------------------------------------- /res/icons/forget-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/forget-email.png -------------------------------------------------------------------------------- /res/icons/plugin_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/plugin_edit.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | web-ext-artifacts 4 | .web-extension-id 5 | UbiquityWE.zip 6 | ubiquity-settings.json -------------------------------------------------------------------------------- /res/icons/document_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/document_create.png -------------------------------------------------------------------------------- /res/icons/document_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/document_delete.png -------------------------------------------------------------------------------- /res/icons/translate_bing.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/translate_bing.ico -------------------------------------------------------------------------------- /commands/more/fontawesome.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/commands/more/fontawesome.woff2 -------------------------------------------------------------------------------- /res/icons/translate_google.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/translate_google.ico -------------------------------------------------------------------------------- /res/icons/ubiquibot-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GChristensen/ubiquitywe/HEAD/res/icons/ubiquibot-square.png -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal 2 | title: Ubiquity WebExtension 3 | logo: res/icons/icon-128.png 4 | description: A text command interface for web browsers -------------------------------------------------------------------------------- /parser/contextutils.js: -------------------------------------------------------------------------------- 1 | // Stub for ContextUtils 2 | 3 | var ContextUtils = {}; 4 | 5 | ContextUtils.getSelectionObject = function (context) { 6 | return {text: CmdUtils.selectedText, html: CmdUtils.selectedHtml, fake: false}; 7 | }; -------------------------------------------------------------------------------- /updates.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "ubiquitywe@firefox": { 4 | "updates": [{ 5 | "version": "0.3.1.31", 6 | "update_link": "https://github.com/GChristensen/ubiquitywe/releases/download/v0.3.1.31/ubiquity_webeextension.xpi" 7 | } 8 | ] 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /lib/ace/ext-error_marker.js: -------------------------------------------------------------------------------- 1 | ; (function() { 2 | ace.require(["ace/ext/error_marker"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /commands/more/fontawesome.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family:'FontAwesome'; 3 | src:url('fontawesome.woff2') format('woff2'); 4 | font-weight:normal; 5 | font-style:normal 6 | } 7 | 8 | .u-link-magnet:before { 9 | font-family: FontAwesome; 10 | content:"\f076"; 11 | } 12 | .u-link-download:before { 13 | text-decoration: none; 14 | font-weight: normal; 15 | font-family: FontAwesome; 16 | content:"\f0ed" 17 | } -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | test: 2 | start web-ext run -p "%APPDATA%/Mozilla/Firefox/Profiles/debug" --keep-profile-changes --browser-console 3 | 4 | sign: 5 | web-ext sign -i ubiquity-settings.json creds web-ext-artifacts marketing screen.png logo.jpg *.md *.iml updates.json `cat $(HOME)/.amo/creds` 6 | 7 | chrome: 8 | rm -f UbiquityWE.zip 9 | 7za a UbiquityWE.zip lib/* res/* commands/* parser/* *.css *.html *.js manifest.json 10 | -------------------------------------------------------------------------------- /commands/more/dark-flow.js: -------------------------------------------------------------------------------- 1 | CmdUtils.CreateCommand({ 2 | name: "dark-flow", 3 | uuid: "79C0722B-5D25-49A3-AE33-9ACA1152EC9C", 4 | argument: [{role: "object", nountype: noun_arb_text, label: "URL"}], 5 | description: "Follow the URL in Dark Flow.", 6 | icon: "/commands/more/dark-flow.png", 7 | builtIn: true, 8 | _hidden: true, 9 | _namespace: NS_MORE_COMMANDS, 10 | execute: function execute({object: {text}}) { 11 | chrome.runtime.sendMessage("dark-flow@firefox", {message: "dark-flow:follow-url", url: text}, null); 12 | }, 13 | preview: "Follow the URL in Dark Flow" 14 | }); -------------------------------------------------------------------------------- /commands/more/kpop.js: -------------------------------------------------------------------------------- 1 | CmdUtils.makeSearchCommand({ 2 | name: "kpop", 3 | uuid: "479E0CB6-981C-4485-AA7B-8296AB383EA7", 4 | url: "https://hulkpop.com/?s=%s", 5 | defaultUrl: "https://hulkpop.com/", 6 | arguments: [{role: "object", nountype: noun_arb_text, label: "query"}], 7 | description: "Search for K-Pop releases.", 8 | icon: "/commands/more/kpop.png", 9 | builtIn: true, 10 | _hidden: true, 11 | _namespace: "More Commands", 12 | previewDelay: 1000, 13 | parser: { 14 | type: "html", 15 | container : "article[id^='post']", 16 | title : ".post-title a", 17 | href : ".post-title a", 18 | thumbnail : ".post-thumbnail img", 19 | body : ".post-meta li:nth-of-type(2)", 20 | maxResults : 20, 21 | display: "previewList2" 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /core.js: -------------------------------------------------------------------------------- 1 | // common script for UI pages that initializes global objects 2 | 3 | var backgroundPage; 4 | switch(window.location.protocol) { 5 | case 'http:': 6 | case 'https:': 7 | case 'file:': // for local file debugging 8 | backgroundPage = window; 9 | var head = document.getElementsByTagName("head")[0]; 10 | var s; 11 | s = document.createElement("script"); 12 | s.type = "text/javascript"; 13 | s.src = "utils.js"; 14 | head.appendChild(s); 15 | s = document.createElement("script"); 16 | s.type = "text/javascript"; 17 | s.src = "cmdutils.js"; 18 | head.appendChild(s); 19 | break; 20 | 21 | case 'chrome-extension:': 22 | default: 23 | backgroundPage = chrome.extension.getBackgroundPage(); 24 | } 25 | 26 | //var backgroundPage = chrome.extension.getBackgroundPage(); 27 | var Utils = backgroundPage.Utils; 28 | var CmdUtils = backgroundPage.CmdUtils; 29 | -------------------------------------------------------------------------------- /selection.js: -------------------------------------------------------------------------------- 1 | function __ubiq_get_sel() { 2 | let sel = window.getSelection(); 3 | 4 | if (sel && !sel.isCollapsed) { 5 | let div = document.createElement('div'); 6 | 7 | try { 8 | for (let i = 0; i < sel.rangeCount; ++i) { 9 | let range = sel.getRangeAt(i); 10 | 11 | if (range.isCollapsed) 12 | continue; 13 | 14 | let parent = range.commonAncestorContainer.nodeType === 3 15 | ? range.commonAncestorContainer.parentNode 16 | : range.commonAncestorContainer; 17 | 18 | parent = parent.cloneNode(false); 19 | 20 | div.appendChild(parent); 21 | div.appendChild(range.cloneContents()); 22 | } 23 | } 24 | catch (e) { 25 | console.log(e); 26 | } 27 | 28 | return {text: sel.toString(), html: div.innerHTML}; 29 | } 30 | } 31 | 32 | __ubiq_get_sel(); 33 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 20 | 21 | 23 | 27 | 28 |
18 | 19 |
22 | 24 |
25 |
26 |
29 |
30 | UbiquityWE 0.1 31 | 32 | -------------------------------------------------------------------------------- /lib/jquery.toc.min.js: -------------------------------------------------------------------------------- 1 | /*! Table of Contents jQuery Plugin - jquery.toc * Copyright (c) 2013-2016 Nikhil Dabas * http://www.apache.org/licenses/LICENSE-2.0 */ 2 | !function(a){"use strict";var b=function(b){return this.each(function(){var c,d,e=a(this),f=e.data(),g=[e],h=this.tagName,i=0;c=a.extend({content:"body",headings:"h1,h2,h3"},{content:f.toc||void 0,headings:f.tocHeadings||void 0},b),d=c.headings.split(","),a(c.content).find(c.headings).attr("id",function(b,c){var d=function(a){0===a.length&&(a="?");for(var b=a.replace(/\s+/g,"_"),c="",d=1;null!==document.getElementById(b+c);)c="_"+d++;return b+c};return c||d(a(this).text())}).each(function(){var b=a(this),c=a.map(d,function(a,c){return b.is(a)?c:void 0})[0];if(c>i){var e=g[0].children("li:last")[0];e&&g.unshift(a("<"+h+"/>").appendTo(e))}else g.splice(0,Math.min(i-c,Math.max(g.length-1,0)));a("
  • ").appendTo(g[0]).append(a("").text(b.text()).attr("href","#"+b.attr("id"))),i=c})})},c=a.fn.toc;a.fn.toc=b,a.fn.toc.noConflict=function(){return a.fn.toc=c,this},a(function(){b.call(a("[data-toc]"))})}(window.jQuery); -------------------------------------------------------------------------------- /res/edit.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | background-color: gray; 4 | font-size: 8pt; 5 | font-family: Calibri, Helvetica, Arial; 6 | } 7 | 8 | a { 9 | color: black; 10 | } 11 | 12 | #panel { 13 | height:100vh; 14 | overflow:hidden; 15 | display: flex; 16 | flex-direction: column; 17 | } 18 | #code { 19 | margin: 0.25%; 20 | flex: 1; 21 | width:99.5%; 22 | box-sizing: border-box; /* For IE and modern versions of Chrome */ 23 | -moz-box-sizing: border-box; /* For Firefox */ 24 | -webkit-box-sizing: border-box; /* For Safari */ 25 | min-height: 200px; 26 | } 27 | 28 | #footer { 29 | margin: 2px; 30 | } 31 | 32 | #info { 33 | display: inline-block; 34 | } 35 | 36 | #buttons { 37 | float: right; 38 | } 39 | 40 | .CodeMirror { 41 | flex: 1; 42 | font-size: 1.5em; 43 | box-sizing: border-box; /* For IE and modern versions of Chrome */ 44 | -moz-box-sizing: border-box; /* For Firefox */ 45 | -webkit-box-sizing: border-box; /* For Safari */ 46 | min-height: 200px; 47 | } -------------------------------------------------------------------------------- /lib/ace/ext-linking.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"],function(e,t,n){function i(e){var n=e.editor,r=e.getAccelKey();if(r){var n=e.editor,i=e.getDocumentPosition(),s=n.session,o=s.getTokenAt(i.row,i.column);t.previousLinkingHover&&t.previousLinkingHover!=o&&n._emit("linkHoverOut"),n._emit("linkHover",{position:i,token:o}),t.previousLinkingHover=o}else t.previousLinkingHover&&(n._emit("linkHoverOut"),t.previousLinkingHover=!1)}function s(e){var t=e.getAccelKey(),n=e.getButton();if(n==0&&t){var r=e.editor,i=e.getDocumentPosition(),s=r.session,o=s.getTokenAt(i.row,i.column);r._emit("linkClick",{position:i,token:o})}}var r=e("ace/editor").Editor;e("../config").defineOptions(r.prototype,"editor",{enableLinking:{set:function(e){e?(this.on("click",s),this.on("mousemove",i)):(this.off("click",s),this.off("mousemove",i))},value:!1}}),t.previousLinkingHover=!1}); (function() { 2 | ace.require(["ace/ext/linking"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /lib/ace/ext-statusbar.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"],function(e,t,n){"use strict";var r=e("ace/lib/dom"),i=e("ace/lib/lang"),s=function(e,t){this.element=r.createElement("div"),this.element.className="ace_status-indicator",this.element.style.cssText="display: inline-block;",t.appendChild(this.element);var n=i.delayedCall(function(){this.updateStatus(e)}.bind(this)).schedule.bind(null,100);e.on("changeStatus",n),e.on("changeSelection",n),e.on("keyboardActivity",n)};(function(){this.updateStatus=function(e){function n(e,n){e&&t.push(e,n||"|")}var t=[];n(e.keyBinding.getStatusText(e)),e.commands.recording&&n("REC");var r=e.selection,i=r.lead;if(!r.isEmpty()){var s=e.getSelectionRange();n("("+(s.end.row-s.start.row)+":"+(s.end.column-s.start.column)+")"," ")}n(i.row+":"+i.column," "),r.rangeCount&&n("["+r.rangeCount+"]"," "),t.pop(),this.element.textContent=t.join("")}}).call(s.prototype),t.StatusBar=s}); (function() { 2 | ace.require(["ace/ext/statusbar"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ##### 31.07.2019 (v.0.3.1.1) 2 | 3 | * Disabled 'maps' command due to the lack of free public Google Maps API. 4 | 5 | ##### 30.07.2019 (v.0.3.1.0) 6 | 7 | * Improved several commands. 8 | * Public command API updates. 9 | 10 | ##### 30.05.2019 (v.0.3.0.0) 11 | 12 | * Added [Scrapyard](https://gchristensen.github.io/scrapyard/) commands. 13 | * Added Libgen command. 14 | * Added Scihub command. 15 | * Improved HTML selection acquisition. 16 | 17 | ##### 14.03.2019 (v.0.2.6.2) 18 | 19 | * Improved "History" command. 20 | * Remember last edited command category. 21 | 22 | ##### 11.10.2018 (v.0.2.5.7) 23 | 24 | * Fixed Google command. 25 | 26 | ##### 10.10.2018 (v.0.2.5.6) 27 | 28 | * Improved selection acquisition over multiple iframes. 29 | 30 | ##### 08.10.2018 (v.0.2.5.5) 31 | 32 | * Improved history command. 33 | 34 | ##### 28.09.2018 (v.0.2.5.3) 35 | 36 | * Fixed settings import feature. 37 | 38 | ##### 27.09.2018 (v.0.2.5.2) 39 | 40 | * Internal improvements: enabled suggestion memory for non-debug modes. 41 | * Internal improvements: added Firefox update manifest. 42 | * Internal improvements: fixed custom script handing in command editor. 43 | * Internal improvements: moved suggestion memory and user commands to IndexedDB. 44 | 45 | ##### 25.09.2018 (v.0.2.4.1) 46 | 47 | * Added keyboard shortcuts to 'YouTube' command. 48 | * New parser prepositions: 'by' and 'for'. 49 | * Added new commands: 50 | * history 51 | * isdown -------------------------------------------------------------------------------- /lib/ace/ext-spellcheck.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event");t.contextMenuHandler=function(e){var t=e.target,n=t.textInput.getElement();if(!t.selection.isEmpty())return;var i=t.getCursorPosition(),s=t.session.getWordRange(i.row,i.column),o=t.session.getTextRange(s);t.session.tokenRe.lastIndex=0;if(!t.session.tokenRe.test(o))return;var u="\x01\x01",a=o+" "+u;n.value=a,n.setSelectionRange(o.length,o.length+1),n.setSelectionRange(0,0),n.setSelectionRange(0,o.length);var f=!1;r.addListener(n,"keydown",function l(){r.removeListener(n,"keydown",l),f=!0}),t.textInput.setInputHandler(function(e){console.log(e,a,n.selectionStart,n.selectionEnd);if(e==a)return"";if(e.lastIndexOf(a,0)===0)return e.slice(a.length);if(e.substr(n.selectionEnd)==a)return e.slice(0,-a.length);if(e.slice(-2)==u){var r=e.slice(0,-2);if(r.slice(-1)==" ")return f?r.substring(0,n.selectionEnd):(r=r.slice(0,-1),t.session.replace(s,r),"")}return e})};var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{spellcheck:{set:function(e){var n=this.textInput.getElement();n.spellcheck=!!e,e?this.on("nativecontextmenu",t.contextMenuHandler):this.removeListener("nativecontextmenu",t.contextMenuHandler)},value:!0}})}); (function() { 2 | ace.require(["ace/ext/spellcheck"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /lib/ace/ext-themelist.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/themelist",["require","exports","module"],function(e,t,n){"use strict";var r=[["Chrome"],["Clouds"],["Crimson Editor"],["Dawn"],["Dreamweaver"],["Eclipse"],["GitHub"],["IPlastic"],["Solarized Light"],["TextMate"],["Tomorrow"],["XCode"],["Kuroir"],["KatzenMilch"],["SQL Server","sqlserver","light"],["Ambiance","ambiance","dark"],["Chaos","chaos","dark"],["Clouds Midnight","clouds_midnight","dark"],["Dracula","","dark"],["Cobalt","cobalt","dark"],["Gruvbox","gruvbox","dark"],["Green on Black","gob","dark"],["idle Fingers","idle_fingers","dark"],["krTheme","kr_theme","dark"],["Merbivore","merbivore","dark"],["Merbivore Soft","merbivore_soft","dark"],["Mono Industrial","mono_industrial","dark"],["Monokai","monokai","dark"],["Pastel on dark","pastel_on_dark","dark"],["Solarized Dark","solarized_dark","dark"],["Terminal","terminal","dark"],["Tomorrow Night","tomorrow_night","dark"],["Tomorrow Night Blue","tomorrow_night_blue","dark"],["Tomorrow Night Bright","tomorrow_night_bright","dark"],["Tomorrow Night 80s","tomorrow_night_eighties","dark"],["Twilight","twilight","dark"],["Vibrant Ink","vibrant_ink","dark"]];t.themesByName={},t.themes=r.map(function(e){var n=e[1]||e[0].replace(/ /g,"_").toLowerCase(),r={caption:e[0],theme:"ace/theme/"+n,isDark:e[2]=="dark",name:n};return t.themesByName[n]=r,r})}); (function() { 2 | ace.require(["ace/ext/themelist"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /res/icons/scrapyard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/uuid.js: -------------------------------------------------------------------------------- 1 | // https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript/24891600#24891600 2 | 3 | var UUID = {}; 4 | 5 | UUID.trueRandom = (function() { 6 | var crypt = window.crypto; 7 | 8 | // if we have a crypto library, use it 9 | var random = function(min, max) { 10 | var rval = 0; 11 | var range = max - min; 12 | if (range < 2) { 13 | return min; 14 | } 15 | 16 | var bits_needed = Math.ceil(Math.log2(range)); 17 | if (bits_needed > 53) { 18 | throw new Exception("We cannot generate numbers larger than 53 bits."); 19 | } 20 | var bytes_needed = Math.ceil(bits_needed / 8); 21 | var mask = Math.pow(2, bits_needed) - 1; 22 | // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 23 | 24 | // Create byte array and fill with N random numbers 25 | var byteArray = new Uint8Array(bytes_needed); 26 | crypt.getRandomValues(byteArray); 27 | 28 | var p = (bytes_needed - 1) * 8; 29 | for(var i = 0; i < bytes_needed; i++ ) { 30 | rval += byteArray[i] * Math.pow(2, p); 31 | p -= 8; 32 | } 33 | 34 | // Use & to apply the mask and reduce the number of recursive lookups 35 | rval = rval & mask; 36 | 37 | if (rval >= range) { 38 | // Integer out of acceptable range 39 | return random(min, max); 40 | } 41 | // Return an integer that falls within the range 42 | return min + rval; 43 | }; 44 | return function() { 45 | var r = random(0, 1000000000) / 1000000000; 46 | return r; 47 | }; 48 | }()); 49 | 50 | UUID.generate = function() { 51 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 52 | var r = UUID.trueRandom() * 16 | 0, 53 | v = c == 'x' ? r : (r & 0x3 | 0x8); 54 | return v.toString(16).toUpperCase(); 55 | }); 56 | }; -------------------------------------------------------------------------------- /parser/suggestion_memory2.js: -------------------------------------------------------------------------------- 1 | function SuggestionMemory2() { 2 | this._table = Utils.suggestionMemory || {__proto__: null}; 3 | } 4 | 5 | SuggestionMemory2.prototype = { 6 | constructor: SuggestionMemory2, 7 | toString() { return "[object SuggestionMemory2]" }, 8 | toJSON() { return this._table }, 9 | 10 | Z: {__proto__: null}, // keep this empty! 11 | 12 | _getScores(input) { 13 | return this._table[input] || (this._table[input] = {__proto__: null}) 14 | }, 15 | 16 | // === {{{ SuggestionMemory#remember(input, suggestion, ammount) }}} 17 | // Increases the strength of the association between {{{input}}} and 18 | // {{{suggestion}}}. 19 | remember: function SM_remember(input, suggestion, ammount) { 20 | ammount = +ammount || 1; 21 | var scores = this._getScores(input); 22 | if (suggestion in scores) { 23 | var score = scores[suggestion] += ammount; 24 | } 25 | else { 26 | var score = scores[suggestion] = ammount; 27 | } 28 | Utils.setPref("suggestionMemory", this._table); 29 | return score; 30 | }, 31 | 32 | // === {{{ SuggestionMemory#getScore(input, suggestion) }}} === 33 | // === {{{ SuggestionMemory#setScore(input, suggestion, score) }}} === 34 | // Gets/Sets the number of times that {{{suggestion}}} has been associated 35 | // with {{{input}}}. 36 | getScore(input, suggestion) { 37 | return (this._table[input] || this.Z)[suggestion] || 0 38 | }, 39 | setScore(input, suggestion, score) { 40 | return this.remember(input, suggestion, score - this.getScore(input, suggestion)); 41 | }, 42 | 43 | // === {{{ SuggestionMemory#wipe(input, suggestion) }}} === 44 | // Wipes the specified entry out of this suggestion memory instance. 45 | // Omitting both {{{input}}} and {{{suggestion}}} deletes everything. 46 | // Be careful with this. 47 | wipe: function SM_wipe(input, suggestion) { 48 | this._table = {__proto__: null}; 49 | Utils.setPref("suggestionMemory", {__proto__: null}); 50 | }, 51 | 52 | }; 53 | -------------------------------------------------------------------------------- /commands/feedsub.js: -------------------------------------------------------------------------------- 1 | CmdUtils.CreateCommand({ 2 | names: ["feedsub"], 3 | uuid: "A2910385-002A-4BBE-AA22-9E92FC06352B", 4 | _namespace: "Syndication", 5 | description: "Subscribe to a RSS feed in Feedly.", 6 | help: `The command uses the URL opened in the current tab. 7 | Direct feed links, Instagram, Tumblr, Twitter and Youtube are supported.`, 8 | icon: "/res/icons/feedly.png", 9 | builtIn: true, 10 | preview: "Subscribe using Feedly", 11 | execute: function () { 12 | const feedlySubUrl = "https://feedly.com/i/subscription/feed/"; 13 | let url = CmdUtils.getLocation(); 14 | if (/twitter.com\//.test(url)) { 15 | let m = url.match(/twitter.com\/([^\/]*)/); 16 | let uid = m? m[1]: null; 17 | if (uid) { 18 | CmdUtils.addTab(feedlySubUrl 19 | + encodeURIComponent("https://twitrss.me/twitter_user_to_rss/?user=" + uid)); 20 | } 21 | } 22 | else if (/tumblr.com/.test(url)) { 23 | let m = url.match(/([^.]*.tumblr.com)/); 24 | let uid = m? m[1]: null; 25 | if (uid) { 26 | CmdUtils.addTab(feedlySubUrl 27 | + encodeURIComponent(uid + "/rss")); 28 | } 29 | } 30 | else if (/instagram.com\//.test(url)) { 31 | let m = url.match(/instagram.com\/([^\/]*)/); 32 | let uid = m? m[1]: null; 33 | if (uid) { 34 | CmdUtils.addTab(feedlySubUrl 35 | + encodeURIComponent("https://rsshub.app/instagram/user/" + uid)); 36 | } 37 | } 38 | else if (/youtube.com\//.test(url)) { 39 | let m = url.match(/youtube.com\/channel\/([^\/]*)/); 40 | let uid = m? m[1]: null; 41 | if (uid) { 42 | CmdUtils.addTab(feedlySubUrl 43 | + encodeURIComponent("https://www.youtube.com/feeds/videos.xml?channel_id=" + uid)); 44 | } 45 | else { 46 | let m = url.match(/youtube.com\/user\/([^\/]*)/); 47 | let uid = m? m[1]: null; 48 | CmdUtils.addTab(feedlySubUrl 49 | + encodeURIComponent("https://www.youtube.com/feeds/videos.xml?user=" + uid)); 50 | } 51 | } 52 | else { 53 | CmdUtils.addTab(feedlySubUrl + encodeURIComponent(url)); 54 | } 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /res/cmenu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | UbiquityWE Context Menu 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 53 | 54 | 55 |
    UbiquityWE: Context Menu
    56 |
    66 | 67 |
    68 |
    69 |

    Add commands to context menu by pressing Ctrl+Alt+Enter in the command line.

    70 |
    71 | 72 |
    73 |

    Context menu commands

    74 |
    75 |
    76 |
    77 | 78 | 5 | 6 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 33 | 35 | 55 | 60 | 61 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.3.1.32", 3 | "name": "Ubiquity WebExtension", 4 | "short_name": "UbiquityWE", 5 | "homepage_url": "https://gchristensen.github.io/ubiquitywe/", 6 | "author": "rostok, gchristnsn", 7 | "description": "WebExtension port of Ubiquity", 8 | "content_security_policy": "script-src 'self' 'unsafe-eval' https://maps.googleapis.com; style-src 'self' 'unsafe-inline'; object-src 'self'", 9 | "applications": { 10 | "gecko": { 11 | "id": "ubiquitywe@firefox", 12 | "strict_min_version": "57.0", 13 | "update_url": "https://github.com/GChristensen/ubiquitywe/blob/master/updates.json?raw=true" 14 | } 15 | }, 16 | "manifest_version": 2, 17 | "background": { 18 | "scripts": [ 19 | "lib/jquery.min.js", 20 | "lib/jsstore.min.js", 21 | "lib/jsstore.worker.min.js", 22 | "lib/template.js", 23 | "lib/math_parser.js", 24 | "lib/uuid.js", 25 | "utils.js", 26 | "parser/contextutils.js", 27 | "cmdutils.js", 28 | "parser/nounutils.js", 29 | "parser/nountypes.js", 30 | "parser/suggestion_memory2.js", 31 | "parser/suggestion_memory3.js", 32 | "parser/parser2.js", 33 | "parser/parser3.js", 34 | "/commands/more/nyaa.js", 35 | "/commands/more/kpop.js", 36 | "/commands/more/javlib.js", 37 | "/commands/more/dark-flow.js", 38 | "commands/builtin.js", 39 | "commands/mail.js", 40 | "commands/translate.js", 41 | "commands/search.js", 42 | "commands/lingvo.js", 43 | "commands/feedsub.js", 44 | "commands/resurrect.js", 45 | "commands/scrapyard.js", 46 | "background.js"], 47 | "persistent":true 48 | }, 49 | "browser_action": { 50 | "default_title": "Ubiquity WebExtension", 51 | "default_popup": "popup.html", 52 | "default_icon": "/res/icons/icon-24.png" 53 | }, 54 | "options_ui": { 55 | "page": "res/options.html", 56 | "open_in_tab": true 57 | }, 58 | "commands": { 59 | "_execute_browser_action": { 60 | "suggested_key": { 61 | "default": "Ctrl+Space", 62 | "chromeos": "Ctrl+Space", 63 | "linux": "Ctrl+Space", 64 | "mac": "Command+Space", 65 | "windows": "Ctrl+Space" 66 | } 67 | } 68 | }, 69 | "icons": { "128" : "/res/icons/icon-128.png" }, 70 | "permissions": [ 71 | "", 72 | "activeTab", 73 | "tabs", 74 | "tabHide", 75 | "clipboardRead", 76 | "clipboardWrite", 77 | "notifications", 78 | "storage", 79 | "contextMenus", 80 | "history", 81 | "webNavigation", 82 | "management" 83 | ] 84 | } -------------------------------------------------------------------------------- /res/cmenu.js: -------------------------------------------------------------------------------- 1 | 2 | $(onDocumentLoad); 3 | 4 | function onDocumentLoad() { 5 | 6 | let commandList = $("#context-menu-commands"); 7 | 8 | for (let cmd of CmdUtils.ContextMenuCommands) { 9 | commandList.append(` 10 | × 11 | 12 | 13 | 14 | 15 | 16 | `); 17 | } 18 | 19 | $("#context-menu-commands .remove-item").click((e) => { 20 | let tr = e.target.parentNode; 21 | if (confirm("Do you really want to delete \"" + $(tr).find("input[name='label']").val() + "\"?")) { 22 | let cm = CmdUtils.getContextMenuCommand($(tr).find("input[name='command']").val()); 23 | let i = CmdUtils.ContextMenuCommands.indexOf(cm); 24 | CmdUtils.ContextMenuCommands.splice(i, 1); 25 | tr.parentNode.removeChild(tr); 26 | CmdUtils.createContextMenu(); 27 | Utils.setPref("contextMenuCommands", CmdUtils.ContextMenuCommands); 28 | } 29 | }); 30 | 31 | $("#context-menu-commands input[name='label']").blur((e) => { 32 | let tr = e.target.parentNode.parentNode; 33 | if (e.target.value) { 34 | let cm = CmdUtils.getContextMenuCommand($(tr).find("input[name='command']").val()); 35 | cm.label = e.target.value; 36 | CmdUtils.createContextMenu(); 37 | Utils.setPref("contextMenuCommands", CmdUtils.ContextMenuCommands); 38 | } 39 | }); 40 | 41 | $("#context-menu-commands input[name='execute']").change((e) => { 42 | let tr = e.target.parentNode.parentNode; 43 | let cm = CmdUtils.getContextMenuCommand($(tr).find("input[name='command']").val()); 44 | cm.execute = e.target.checked; 45 | Utils.setPref("contextMenuCommands", CmdUtils.ContextMenuCommands); 46 | }); 47 | 48 | Utils.getPref("rememberContextMenuCommands", rememberContextMenuCommands => { 49 | let cmHistorySwitch = $("#cm-history-switch"); 50 | cmHistorySwitch.prop("checked", !rememberContextMenuCommands); 51 | CmdUtils.rememberContextMenuCommands = rememberContextMenuCommands; 52 | cmHistorySwitch.change((e) => { 53 | CmdUtils.rememberContextMenuCommands = !e.target.checked; 54 | Utils.setPref("rememberContextMenuCommands", CmdUtils.rememberContextMenuCommands); 55 | }); 56 | }); 57 | 58 | } -------------------------------------------------------------------------------- /res/icons/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 23 | 25 | 26 | 28 | image/svg+xml 29 | 31 | 32 | 33 | 34 | 35 | 37 | 57 | 61 | 66 | 71 | 76 | 77 | -------------------------------------------------------------------------------- /lib/ace/ext-whitespace.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/whitespace",["require","exports","module","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../lib/lang");t.$detectIndentation=function(e,t){function c(e){var t=0;for(var r=e;r0&&!(s%l)&&!(f%l)&&(r[l]=(r[l]||0)+1),n[f]=(n[f]||0)+1}s=f}while(up.score&&(p={score:v,length:u})}if(p.score&&p.score>1.4)var m=p.length;if(i>d+1){if(m==1||di+1)return{ch:" ",length:m}},t.detectIndentation=function(e){var n=e.getLines(0,1e3),r=t.$detectIndentation(n)||{};return r.ch&&e.setUseSoftTabs(r.ch==" "),r.length&&e.setTabSize(r.length),r},t.trimTrailingSpace=function(e,t){var n=e.getDocument(),r=n.getAllLines(),i=t&&t.trimEmpty?-1:0,s=[],o=-1;t&&t.keepCursorPosition&&(e.selection.rangeCount?e.selection.rangeList.ranges.forEach(function(e,t,n){var r=n[t+1];if(r&&r.cursor.row==e.cursor.row)return;s.push(e.cursor)}):s.push(e.selection.getCursor()),o=0);var u=s[o]&&s[o].row;for(var a=0,f=r.length;ai&&(c=s[o].column),o++,u=s[o]?s[o].row:-1),c>i&&n.removeInLine(a,c,l.length)}},t.convertIndentation=function(e,t,n){var i=e.getTabString()[0],s=e.getTabSize();n||(n=s),t||(t=i);var o=t==" "?t:r.stringRepeat(t,n),u=e.doc,a=u.getAllLines(),f={},l={};for(var c=0,h=a.length;c { 26 | let insert = rows.length === 0; 27 | let scores; 28 | 29 | if (insert) 30 | scores = {__proto__: null}; 31 | else 32 | scores = rows[0].scores; 33 | 34 | if (suggestion in scores) { 35 | scores[suggestion] += amount; 36 | } 37 | else { 38 | scores[suggestion] = amount; 39 | } 40 | 41 | if (insert) { 42 | this._connection.insert({ 43 | into: "SuggestionMemory", 44 | values: [{input: input, scores: scores}] 45 | }); 46 | } 47 | else { 48 | this._connection.update({ 49 | in: "SuggestionMemory", 50 | set: {scores: scores}, 51 | where: {input: input} 52 | }); 53 | } 54 | }); 55 | }, 56 | 57 | // === {{{ SuggestionMemory#getScore(input, suggestion) }}} === 58 | // === {{{ SuggestionMemory#setScore(input, suggestion, score) }}} === 59 | // Gets/Sets the number of times that {{{suggestion}}} has been associated 60 | // with {{{input}}}. 61 | getScore(input, suggestion) { 62 | return this._connection.select({ 63 | from: "SuggestionMemory", 64 | where: {input: input} 65 | }) 66 | .then(rows => { 67 | if (rows.length === 0) 68 | return 0; 69 | return rows[0].scores[suggestion] || 0; 70 | }); 71 | }, 72 | setScore(input, suggestion, score) { 73 | //return this.remember(input, suggestion, score - this.getScore(input, suggestion)); 74 | }, 75 | 76 | // === {{{ SuggestionMemory#wipe(input, suggestion) }}} === 77 | // Wipes the specified entry out of this suggestion memory instance. 78 | // Omitting both {{{input}}} and {{{suggestion}}} deletes everything. 79 | // Be careful with this. 80 | wipe: function SM_wipe(input, suggestion) { 81 | 82 | }, 83 | 84 | }; 85 | } -------------------------------------------------------------------------------- /res/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | UbiquityWE Settings 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 |
    UbiquityWE: Settings
    20 | 30 | 31 |
    32 | 33 |
    34 |

    You can get to this page at any time using the “change-ubiquity-settings” command.

    35 |
    36 | 37 |
    38 |

    Web API Settings

    39 |
    ABBYY LingvoLive API Key
    40 |
    41 |  ?
    43 |
    Bing Translator API v3 Key
    44 |
    45 |  ?
    47 |
    48 | 49 |
    50 |

    Version Information

    51 |

    You are using UbiquityWE v

    52 | 53 |

    Language Settings

    54 |

    55 | Command parser language: 56 | 58 |

    59 | 60 |

    Miscellaneous Settings

    61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
    Maximum number of suggestions:
    Maximum number of search results?:
    71 |

    Import/Export

    72 | 73 | 74 | 75 |
    76 | 77 | 13 | 14 | 15 |
    16 |
    17 |

    {{ site.title | default: site.github.repository_name }}

    18 | 19 | {% if site.logo %} 20 | Logo 21 | {% endif %} 22 | 23 |

    {{ site.description | default: site.github.project_tagline }}

    24 | 25 | {% if site.github.is_project_page %} 26 |

    View the Project on GitHub {{ site.github.repository_nwo }}

    27 | {% endif %} 28 | 29 |

    Software by g/christensen gchristensen.github.io

    30 | 31 | {% if site.github.is_user_page %} 32 |

    View My GitHub Profile

    33 | {% endif %} 34 | 35 |

    ❤️ Support the Project

    36 | 37 | {% if site.show_downloads %} 38 | 43 | {% endif %} 44 |
    45 |
    46 | 47 |

    Ubiquity WebExtension

    48 | 49 |

    Firefox 50 | Firefox Add-On 51 | 54 | :: Youtube 55 | Video Manual 56 |

    57 | 58 | 89 | 90 |
    91 |
    92 | 93 | screen 94 |
    96 |
    97 |
    98 | 99 | 102 | 103 |

    SEE ALSO: Enso open-source, 104 | Add Torrent

    105 | 106 |

    DISCONTINUED

    107 | 108 |

    The addon is no longer supported. Please see iShell.

    109 | 110 |

    Description

    111 |

    The add-on was an experimental descendant of the original Ubiquity 112 | project by Mozilla. Please see the new iShell for more features and APIs. 113 |

    114 | 115 |
    116 |
    117 |
    118 |
    119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /commands/more/javlib.js: -------------------------------------------------------------------------------- 1 | { 2 | const JAVLIB_SEARCH_URL = "https://www.javlibrary.com/en/vl_searchbyid.php?keyword="; 3 | 4 | function fix_href(a, return_url) { 5 | if (a) { 6 | let tail = a.href.split("/"); 7 | tail = tail[tail.length - 1]; 8 | a.href = "https://www.javlibrary.com/en/" + tail; 9 | 10 | return return_url ? a.href : a.outerHTML; 11 | } 12 | return ""; 13 | } 14 | 15 | function get_data(pblock, data, xhr) { 16 | 17 | let page = jQuery(data); 18 | let html = ""; 19 | 20 | let img = page.find("#video_jacket_img").get(0); 21 | if (img && img.src) { 22 | let rect = pblock.getBoundingClientRect(); 23 | html += ``; 25 | 26 | let info = page.find("#video_info"); 27 | 28 | if (info) { 29 | let movie_id = info.find("#video_id .text").text(); 30 | let release_date = info.find("#video_date .text").text(); 31 | let video_length = info.find("#video_length .text").parent().text(); 32 | let director = fix_href(info.find("#video_director .director a")[0]); 33 | let maker = fix_href(info.find("#video_maker .maker a")[0]); 34 | let label = fix_href(info.find("#video_label .label a")[0]); 35 | 36 | html += `
    ${movie_id} | ${release_date} 37 | | ${video_length}${director ? "| By " + director : ""} | ${maker}/${label}
    `; 38 | 39 | html += `
    Genres: `; 40 | info.find("#video_genres .genre a").map((_, g) => html += fix_href(g) + " "); 41 | html += `
    `; 42 | 43 | html += `
    Cast: `; 44 | info.find("#video_cast .star a").map((_, s) => html += fix_href(s) + " "); 45 | html += `
    `; 46 | } 47 | 48 | pblock.innerHTML = html; 49 | 50 | if (pblock.scrollHeight === pblock.clientHeight) 51 | jQuery(pblock).find("#javlib-cover").width(538); 52 | 53 | let alt_img = img.getAttribute("onerror"); 54 | if (alt_img) { 55 | let alt_url_match = alt_img.match(/['"](https?:)?(\/\/)?([^'"]+)['"]/); 56 | if (alt_url_match) 57 | $(pblock).find("#javlib-cover").on("error", (e) => {e.target.src = "https://" + alt_url_match[3]}); 58 | } 59 | } 60 | else if (page.find(".videos .video").length > 0) { 61 | page.find(".videos .video > a > .id") 62 | .map((_, id) => html += `${id.textContent} `); 63 | pblock.innerHTML = html; 64 | jQuery(pblock).find("a").click((e) => { 65 | e.preventDefault(); 66 | make_request(pblock, e.target.href); 67 | }); 68 | } 69 | else { 70 | pblock.innerHTML = "Not found."; 71 | } 72 | } 73 | 74 | let cloudflare = false; 75 | let updated_url = ""; 76 | function make_request(pblock, url) { 77 | let options = { 78 | url: url, 79 | dataType: "html", 80 | success: function (data) { 81 | cloudflare = false; 82 | get_data(pblock, data, this); 83 | }, 84 | statusCode: { 85 | 503: function (xhr) { 86 | updated_url = url; 87 | 88 | if (!cloudflare) { 89 | cloudflare = true; 90 | pblock.innerHTML = "Waiting for Cloudflare..."; 91 | 92 | let seed = Math.floor(Math.random() * 100000); 93 | 94 | chrome.tabs.create({ 95 | active: false, 96 | url: "https://www.javlibrary.com/en/" // + "?__seed=" + seed 97 | }, new_tab => { 98 | let listener = (id, changed, tab) => { 99 | if (id === new_tab.id && changed.title && changed.title.includes("JAVLibrary")) { 100 | chrome.tabs.onUpdated.removeListener(listener); 101 | 102 | cloudflare = false; 103 | chrome.tabs.remove(new_tab.id); 104 | 105 | options.url = updated_url; 106 | CmdUtils.previewAjax(pblock, options); 107 | } 108 | }; 109 | chrome.tabs.onUpdated.addListener(listener, {urls: ["*://*.javlibrary.com/*"]}); 110 | }); 111 | } 112 | } 113 | }, 114 | error: function (xhr) { 115 | //pblock.innerHTML = "Error. Try to wipe javlibrary.com cookies."; 116 | } 117 | }; 118 | 119 | CmdUtils.previewAjax(pblock, options); 120 | } 121 | 122 | CmdUtils.CreateCommand({ 123 | names: ["javlibrary", "idols"], 124 | uuid: "2464CA49-78EF-425E-8A49-ED5F5EA121D0", 125 | argument: [{role: "object", nountype: noun_arb_text, label: "movie code"}], 126 | description: "Search for movie information at javlibrary.", 127 | help: `Try: javlib star-699`, 128 | icon: "/commands/more/jav.png", 129 | builtIn: true, 130 | previewDelay: 1000, 131 | _hidden: true, 132 | _namespace: NS_MORE_COMMANDS, 133 | execute: function execute({object: {text}}) { 134 | Utils.openUrlInBrowser(JAVLIB_SEARCH_URL + encodeURI(text.trim())); 135 | }, 136 | preview: function preview(pblock, {object: {text}}) { 137 | if (text) { 138 | make_request(pblock, JAVLIB_SEARCH_URL + encodeURI(text.trim())); 139 | } 140 | }, 141 | }); 142 | 143 | } -------------------------------------------------------------------------------- /commands/resurrect.js: -------------------------------------------------------------------------------- 1 | // Try to resurrect a dead page using Internet archiving services 2 | // The original idea is taken from here: https://gist.github.com/71580 3 | 4 | // (C) 2011 g/christensen (gchristnsn@gmail.com) 5 | 6 | { 7 | 8 | var resurrect_commandIcon = "/res/icons/resurrect.gif"; 9 | 10 | var resurrect_archiveServices = 11 | { 12 | "wayback machine latest": ["web.archive.org", "http://web.archive.org/web/"] 13 | , "wayback machine list": ["web.archive.org", "http://web.archive.org/web/*/"] 14 | , "google cache": ["google.com", "http://www.google.com/search?q=cache:"] 15 | , "google cache text only": ["google.com", "http://www.google.com/search?strip=1&q=cache:"] 16 | , "coralcdn": ["coralcdn.org", function (loc) { 17 | return loc.split(/\/+/g)[loc.indexOf("://") > 0 ? 1 : 0] + ".nyud.net"; 18 | }] 19 | , "webcite": ["webcitation.org", "http://webcitation.org/query.php?url="] 20 | }; 21 | 22 | 23 | function get_target(input) { 24 | var params = {}; 25 | 26 | if (input.object.text) // Typed-in target or selected URL 27 | { 28 | params.location = input.object.text; 29 | } 30 | else { 31 | /* var html = CmdUtils.getHtmlSelection(); 32 | 33 | if (html) // Check for a HTML link in the selection 34 | { 35 | var a = jQuery(html).find("a:first").get(0); 36 | if (a) 37 | params.location = a.href; 38 | } 39 | 40 | if (CmdUtils.getLocation()) // There is no link 41 | { 42 | var text = CmdUtils.getSelection(); // Try plain text selection 43 | 44 | if (text) 45 | { 46 | params.location = text; 47 | } 48 | else 49 | { 50 | var doc = CmdUtils.getDocument(); 51 | if (doc.title) 52 | { 53 | // Won't be accurate if 404ed, though 54 | params.name = doc.title + " (" + doc.location.hostname + ")"; 55 | } 56 | else 57 | { 58 | params.name = "this page"; 59 | } 60 | 61 | params.location = doc.location.href; 62 | } 63 | }*/ 64 | 65 | params.location = CmdUtils.getLocation(); 66 | } 67 | 68 | if (!params.name) 69 | params.name = params.location; 70 | 71 | return params; 72 | } 73 | 74 | CmdUtils.CreateCommand( 75 | { 76 | names: ["resurrect"], 77 | uuid: "39324f28-48b0-47f5-a22e-fabeb3305705", 78 | /*---------------------------------------------------------------------------*/ 79 | arguments: [{role: "object", nountype: noun_arb_text, label: "URL"}, 80 | { 81 | role: "instrument", nountype: jQuery.map(resurrect_archiveServices, 82 | function (v, k) { 83 | return k 84 | }), 85 | label: "archiving service" 86 | }], 87 | /*---------------------------------------------------------------------------*/ 88 | description: "Resurrect a dead page using Internet archiving services.", 89 | /*---------------------------------------------------------------------------*/ 90 | help: `Syntax
    • resurrect [URL] [with archiving service]
    91 | Arguments
    92 |
      93 |
    • - archiving service - one of the following archiving services: 94 |
        95 |
      • - wayback machine latest
      • 96 |
      • - wayback machine list
      • 97 |
      • - google cache
      • 98 |
      • - google cache text only
      • 99 |
      • - coralcdn
      • 100 |
      • - webcite
      • 101 |
    • 102 |
    103 | Example 104 |
    • resurrect http://en.beijing2008.cn with wayback machine list
    `, 105 | /*---------------------------------------------------------------------------*/ 106 | icon: resurrect_commandIcon, 107 | /*---------------------------------------------------------------------------*/ 108 | author: {name: "g/christensen"}, 109 | /*---------------------------------------------------------------------------*/ 110 | builtIn: true, _namespace: "Search", 111 | /*---------------------------------------------------------------------------*/ 112 | license: "GPL", 113 | /*---------------------------------------------------------------------------*/ 114 | preview: function (pblock, input) { 115 | var target = get_target(input); 116 | var instrument = input.instrument? input.instrument.summary: ""; 117 | 118 | if (instrument === "") 119 | instrument = (function () { 120 | for (first in resurrect_archiveServices) 121 | break; 122 | return first; 123 | })(); 124 | 125 | var service = resurrect_archiveServices[instrument][0]; 126 | 127 | pblock.innerHTML = _("Opens the most recent archived version of " 128 | + target.name + " using the " + service + ""); 130 | }, 131 | /*---------------------------------------------------------------------------*/ 132 | execute: function (input) { 133 | var target = get_target(input); 134 | var instrument = input.instrument? input.instrument.summary: ""; 135 | 136 | if (instrument == "") 137 | instrument = (function () { 138 | for (first in resurrect_archiveServices) 139 | break; 140 | return first; 141 | })(); 142 | 143 | var handler = resurrect_archiveServices[instrument][1]; 144 | 145 | if (typeof handler === "string") { 146 | Utils.openUrlInBrowser(handler + target.location); 147 | } 148 | else { 149 | Utils.openUrlInBrowser(handler(target.location)); 150 | } 151 | } 152 | }); 153 | } -------------------------------------------------------------------------------- /lib/jsstore.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @license :jsstore - V2.4.1 - 11/09/2018 3 | * https://github.com/ujjwalguptaofficial/JsStore 4 | * Copyright (c) 2018 @Ujjwal Gupta; Licensed MIT 5 | */ 6 | var JsStore=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";var r,o,i,u,s;n.r(t),function(e){e.WorkerNotSupplied="worker_not_supplied",e.IndexedDbUndefined="indexeddb_undefined"}(r||(r={})),function(e){e.Registered="registerd",e.Failed="failed",e.NotStarted="not_started"}(o||(o={})),function(e){e.String="string",e.Object="object",e.Array="array",e.Number="number",e.Boolean="boolean",e.Null="null",e.DateTime="date_time"}(i||(i={})),function(e){e.PrimaryKey="primary_key",e.AutoIncrement="auto_increment",e.Unique="unique",e.NotNull="not_null",e.MultiEntry="multi_entry"}(u||(u={})),function(e){e.CreateDb="create_db",e.IsDbExist="is_db_exist",e.GetDbVersion="get_db_version",e.GetDbList="get_db_list",e.Get="get",e.Set="set",e.Select="select",e.Insert="insert",e.Update="update",e.Remove="remove",e.GetDbSchema="get_db_schema",e.OpenDb="open_db",e.Clear="clear",e.DropDb="drop_db",e.Count="count",e.BulkInsert="bulk_insert",e.ExportJson="export_json",e.ChangeLogStatus="change_log_status",e.Terminate="terminate",e.Transaction="transaction"}(s||(s={}));var c=function(){function e(){}return e.isLogEnabled=!1,e.isRuningInWorker=!0,e}(),p=function(){function e(e,t){void 0===t&&(t=null),this.type=e,this._info=t,this.message=this.getMsg()}return e.prototype.throw=function(){throw this.get()},e.log=function(e){c.isLogEnabled&&console.log(e)},e.prototype.logError=function(){console.error(this.get())},e.prototype.logWarning=function(){console.warn(this.get())},e.prototype.get=function(){return{message:this.message,type:this.type}},e.prototype.getMsg=function(){var e;switch(this.type){case r.WorkerNotSupplied:e="Worker object is not passed in instance constructor";break;case r.IndexedDbUndefined:e="Browser does not support indexeddb";break;default:e=this.message}return e},e}(),a=function(){function e(e){this.isDbOpened_=!1,this.requestQueue_=[],this.isCodeExecuting_=!1,this.whiteListApi_=[s.CreateDb,s.IsDbExist,s.GetDbVersion,s.GetDbList,s.OpenDb,s.GetDbSchema,s.Get,s.Set,s.ChangeLogStatus,s.Terminate],e?(this.worker_=e,this.worker_.onmessage=this.onMessageFromWorker_.bind(this)):(c.isRuningInWorker=!1,this.queryExecutor_=new JsStoreWorker.QueryExecutor(this.processFinishedQuery_.bind(this)))}return e.prototype.onMessageFromWorker_=function(e){this.processFinishedQuery_(e.data)},e.prototype.processFinishedQuery_=function(e){var t=this.requestQueue_.shift();if(t){if(p.log("request finished : "+t.name),e.errorOccured)t.onError&&t.onError(e.errorDetails);else if(t.onSuccess){["open_db","create_db"].indexOf(t.name)>=0&&(this.isDbOpened_=!0),t.onSuccess(e.returnedValue)}this.isCodeExecuting_=!1,this.executeQry_()}},e.prototype.pushApi=function(e){var t=this;return new Promise(function(n,r){e.onSuccess=function(e){n(e)},e.onError=function(e){r(e)},t.prcoessExecutionOfQry_(e)})},e.prototype.prcoessExecutionOfQry_=function(e){this.requestQueue_.push(e),this.executeQry_(),p.log("request pushed: "+e.name)},e.prototype.executeQry_=function(){var e=this;if(!this.isCodeExecuting_&&this.requestQueue_.length>0){if(this.isDbOpened_)return void this.sendRequestToWorker_(this.requestQueue_[0]);var t=this.requestQueue_.findIndex(function(t){return e.whiteListApi_.indexOf(t.name)>=0});t>=0&&(this.requestQueue_.splice(0,0,this.requestQueue_.splice(t,1)[0]),this.sendRequestToWorker_(this.requestQueue_[0]))}},e.prototype.sendRequestToWorker_=function(e){if(this.isCodeExecuting_=!0,p.log("request executing : "+e.name),e.name===s.Terminate)!0===c.isRuningInWorker&&this.worker_.terminate(),this.isDbOpened_=!1,this.processFinishedQuery_({returnedValue:null});else{var t={name:e.name,query:e.query};!0===c.isRuningInWorker?this.worker_.postMessage(t):this.queryExecutor_.checkConnectionAndExecuteLogic(t)}},e}(),h=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),f=function(e){function t(t){return e.call(this,t)||this}return h(t,e),t.prototype.openDb=function(e){return this.pushApi({name:s.OpenDb,query:e})},t.prototype.createDb=function(e){return this.pushApi({name:s.CreateDb,query:e})},t.prototype.dropDb=function(){return this.pushApi({name:s.DropDb,query:null})},t.prototype.select=function(e){return this.pushApi({name:s.Select,query:e})},t.prototype.count=function(e){return this.pushApi({name:s.Count,query:e})},t.prototype.insert=function(e){return this.pushApi({name:s.Insert,query:e})},t.prototype.update=function(e){return this.pushApi({name:s.Update,query:e})},t.prototype.remove=function(e){return this.pushApi({name:s.Remove,query:e})},t.prototype.clear=function(e){return this.pushApi({name:s.Clear,query:e})},t.prototype.bulkInsert=function(e){return this.pushApi({name:s.BulkInsert,query:e})},t.prototype.exportJson=function(e){var t=this;return new Promise(function(n,r){t.pushApi({name:s.ExportJson,query:e}).then(function(t){!function(t){var n=document.createElement("a");n.href=t,n.download=e.from+".json",n.click()}(t),n()}).catch(function(e){r(e)})})},t.prototype.setLogStatus=function(e){c.isLogEnabled=e||c.isLogEnabled,this.pushApi({name:s.ChangeLogStatus,query:c.isLogEnabled})},t.prototype.getDbVersion=function(e){return this.pushApi({name:s.GetDbVersion,query:e})},t.prototype.isDbExist=function(e){return this.pushApi({name:s.IsDbExist,query:e})},t.prototype.getDbList=function(){return this.pushApi({name:s.GetDbList,query:null})},t.prototype.getDbSchema=function(e){return this.pushApi({name:s.GetDbSchema,query:e})},t.prototype.get=function(e){return this.pushApi({name:s.Get,query:e})},t.prototype.set=function(e,t){return this.pushApi({name:s.Set,query:{key:e,value:t}})},t.prototype.terminate=function(){return this.pushApi({name:s.Terminate,query:null})},t.prototype.transaction=function(e){return e.logic=e.logic.toString(),this.pushApi({name:s.Transaction,query:e})},t}(a),l=function(){c.isLogEnabled=!0},d=function(){function e(e){this.name=e}return e.prototype.options=function(e){var t=this;return e.forEach(function(e){switch(e){case u.AutoIncrement:t.autoIncrement=!0;break;case u.MultiEntry:t.multiEntry=!0;break;case u.NotNull:t.notNull=!0;break;case u.PrimaryKey:t.primaryKey=!0;break;case u.Unique:t.unique=!0}}),this},e.prototype.setDataType=function(e){return this.dataType=e,this},e.prototype.setDefault=function(e){return this.default=e,this},e.prototype.disableSearch=function(){return this.enableSearch=!1,this},e}();n.d(t,"Instance",function(){return f}),n.d(t,"ERROR_TYPE",function(){return r}),n.d(t,"WORKER_STATUS",function(){return o}),n.d(t,"DATA_TYPE",function(){return i}),n.d(t,"COL_OPTION",function(){return u}),n.d(t,"API",function(){return s}),n.d(t,"Config",function(){return c}),n.d(t,"enableLog",function(){return l}),n.d(t,"Column",function(){return d})}]); -------------------------------------------------------------------------------- /commands/translate.js: -------------------------------------------------------------------------------- 1 | { 2 | const MS_TRANSLATOR_LIMIT = 1e4; 3 | 4 | function defaultLanguage(code2name, exclude) { 5 | for (let code of [chrome.i18n.getUILanguage()].concat(CmdUtils.acceptLanguages)) { 6 | if (!(code = code.trim())) continue; 7 | code = (/^(..-)(..)$/i.test(code) 8 | ? RegExp.$1.toLowerCase() + RegExp.$2.toUpperCase() 9 | : code.slice(0, 2).toLowerCase()); 10 | if (code === exclude) continue; 11 | let name = code2name[code]; 12 | if (name) return {name: name, code: code} 13 | } 14 | return {name: code2name["en"], code: "en"} 15 | } 16 | 17 | function translate(target, from, to, back) { 18 | if (!to) return void 19 | msTranslator("Detect", {text: target.text}, function detected(code) { 20 | translate(target, from, defaultLanguage(noun_type_lang_microsoft.MS_LANGS_REV, code).code, back) 21 | }); 22 | let {html} = target 23 | // bitbucket#29: The API doesn't like apostrophes HTML-escaped. 24 | ~html.indexOf('<') || (html = html.replace(/'/g, "'")); 25 | 26 | (CmdUtils.microsoftTranslatorAPIKey? msTranslator_v3: msTranslator) 27 | ("Translate", { 28 | contentType: "text/html", text: html, from: from, to: to, 29 | }, back); 30 | } 31 | 32 | function msTranslator_v3(method, params, back) { 33 | //CmdUtils.deblog("Using Bing Translate API v3"); 34 | let url = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0"; 35 | if (params.from) 36 | url += "&from=" + params.from; 37 | url += "&to=" + params.to; 38 | url += "&textType=html"; 39 | $.ajax({ 40 | url: url, 41 | method: "POST", 42 | data: JSON.stringify([{Text: params.text}]), 43 | headers: {"Content-Type": "application/json", 44 | "Ocp-Apim-Subscription-Key": CmdUtils.microsoftTranslatorAPIKey}, 45 | success : function (json) { 46 | if (json && json.length > 0) { 47 | back(json[0].translations[0].text); 48 | } 49 | }, 50 | error : function (e) { 51 | CmdUtils.notify({title: "Microsoft Translator API v3", text: "(>_<)"}) 52 | }, 53 | }) 54 | } 55 | 56 | function msTranslator(method, params, back) { 57 | params.appId = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+ Math.floor(Math.random() * 10); 58 | $.ajax({ 59 | url: "http://api.microsofttranslator.com/V2/Ajax.svc/" + method, 60 | data: params, 61 | success : function mst_ok(json) { back(JSON.parse(json)) }, 62 | error : function mst_ng() { 63 | CmdUtils.notify({title: "Microsoft Translator", text: "(>_<)"}) 64 | }, 65 | }) 66 | } 67 | 68 | CmdUtils.CreateCommand({ 69 | name: "translate", 70 | uuid: "43599939-571E-4EBF-AF64-8AD6F39C7B79", 71 | description: "Translates from one language to another using Bing Translator.", 72 | _namespace: "Translation", 73 | icon: "/res/icons/translate_bing.ico", 74 | arguments: { 75 | object: noun_arb_text, 76 | source: noun_type_lang_microsoft, 77 | goal: noun_type_lang_microsoft 78 | }, 79 | builtIn: true, 80 | previewDelay: 1000, 81 | help: 82 | `Syntax 83 |
      84 |
    • translate {[this] | text} [from language] [to language]
    • 85 |
    86 | Arguments
    87 |
      88 |
    • - language - a valid language name supported by Bing Translator
    • 89 |
    90 | Example 91 |
      92 |
    • translate mother from english to chinese
    • 93 |
    94 |

    It works on the selected text in any web page, but there is a limit (a couple of paragraphs) 95 | to how much it can translate at once. 96 | If you want to translate a lot of text, use translate-page command instead.

    `, 97 | author: "satyr", 98 | execute: function translate_execute({object, goal, source}) { 99 | let from = "", to = ""; 100 | 101 | if (source && source.data) 102 | from = source.data; 103 | 104 | if (goal && goal.data) 105 | to = goal.data; 106 | 107 | if (object.text && object.text.length <= MS_TRANSLATOR_LIMIT) 108 | translate(object, from, to, CmdUtils.setSelection.bind(CmdUtils)); 109 | else 110 | CmdUtils.deblog("Error performing translation: no text or text exceeded limits"); 111 | }, 112 | preview: function translate_preview(pblock, {object, goal, source}) { 113 | let limitExceeded = CmdUtils.microsoftTranslatorAPIKey 114 | ? object.text.length > MS_TRANSLATOR_LIMIT / 2 115 | : object.text.length > MS_TRANSLATOR_LIMIT; 116 | let from = "", to = ""; 117 | 118 | if (source && source.data) 119 | from = source.data; 120 | 121 | if (goal && goal.data) 122 | to = goal.data; 123 | 124 | if (!object.text || limitExceeded) { 125 | let ph = ""; 126 | if (limitExceeded) 127 | ph += '

    ' + 128 | _("The text you selected exceeds the API limit.") + 129 | ''; 130 | pblock.innerHTML = ph; 131 | return; 132 | } 133 | 134 | pblock.innerHTML = _("Translating the selected text..."); 135 | translate( 136 | object, from, to, 137 | CmdUtils.previewCallback(pblock, function show(html) { 138 | pblock.innerHTML = html 139 | })) 140 | } 141 | }); 142 | 143 | 144 | CmdUtils.CreateCommand({ 145 | names: ["translate-page"], 146 | uuid: "9A6DFBFE-3BB6-4131-996A-25FB0E9B7A26", 147 | _namespace: "Translation", 148 | description: `Translates a whole page to the specified language using 149 | Google Translate.`, 150 | icon: "/res/icons/translate_google.ico", 151 | author: "satyr", 152 | builtIn: true, 153 | arguments: { 154 | object: noun_arb_text, 155 | goal: noun_type_lang_google, 156 | }, 157 | execute: function gtranslate_execute({object, goal}) { 158 | if (!object.text) 159 | object.text = CmdUtils.getLocation(); 160 | 161 | Utils.openUrlInBrowser( 162 | "http://translate.google.com/translate" + 163 | Utils.paramsToString({ 164 | u: object.text, 165 | tl: goal.data || "en", 166 | })); 167 | }, 168 | preview: function gtranslate_preview(pb, {object, goal}) { 169 | if (!object.text) 170 | object.text = CmdUtils.getLocation(); 171 | 172 | let url = (object && object.text)? Utils.escapeHtml(object.text): ""; 173 | let lang = (goal && goal.text && goal.text !== object.text)? goal.text: "English"; 174 | 175 | pb.innerHTML =`Translates ${url} to ${lang}.`; 176 | }, 177 | }) 178 | } -------------------------------------------------------------------------------- /res/commands.js: -------------------------------------------------------------------------------- 1 | var {escapeHtml} = Utils; 2 | var commandCategoryCount = 0; 3 | 4 | function setupHelp(clickee, help) { 5 | var toggler = jQuery(clickee).click(function toggleHelp() { 6 | jQuery(help)[(this.off ^= 1) ? "slideUp" : "slideDown"](); 7 | [this.textContent, this.bin] = [this.bin, this.textContent]; 8 | })[0]; 9 | toggler.textContent = "Show help"; 10 | toggler.bin = "Hide help"; 11 | toggler.off = true; 12 | } 13 | 14 | function A(url, text, className, attrs) { 15 | var a = document.createElement("a"); 16 | a.href = url; 17 | a.textContent = text || url; 18 | if (className) a.className = className; 19 | for (let attr in attrs) a.setAttribute(attr, attrs[attr]); 20 | return a; 21 | } 22 | 23 | function actionLink(text, action) { 24 | return jQuery("").text(text).click(action).addClass("action") 25 | } 26 | 27 | function fillTableCellForFeed(cell, feed, subtext) { 28 | cell.append( 29 | A("#", feed, ""), 30 | "
    "); 31 | cell.append(jQuery('

    ' + 32 | '
    ' + subtext + '
    ' 33 | + '
    ')) 34 | } 35 | 36 | function formatMetaData(md) { 37 | var contributors = md.contributors || (md.contributor? [md.contributor]: []); 38 | var authors = md.authors || (md.author? [md.author]: []); 39 | 40 | if (authors && contributors.length > 0) 41 | authors = authors.concat(contributors); 42 | 43 | var {license, homepage} = md; 44 | function span(data, format, klass, lkey) { 45 | return !data ? "" : ( 46 | '' 47 | + format(data) + 48 | '') 49 | } 50 | 51 | var result = ('
    ' 52 | + (license? license + ' ': '') 53 | + (license && authors.length > 0? ' | ': '') 54 | + (authors.length > 0? 'Authors: ': '') 55 | + span(authors, formatAuthors, "author", "createdby") 56 | + (homepage? ' ': '') 57 | + '
    '); 58 | return result; 59 | 60 | } 61 | 62 | function formatAuthors(authors) { 63 | return ([].concat(authors)).map(a => formatAuthor(a)).join(", "); 64 | } 65 | 66 | function formatAuthor(authorData) { 67 | if (!authorData) return ""; 68 | 69 | if (typeof authorData === "string") return escapeHtml(authorData); 70 | 71 | var authorMarkup = ""; 72 | if ("name" in authorData && !("email" in authorData)) { 73 | authorMarkup += escapeHtml(authorData.name) + " "; 74 | } 75 | else if ("email" in authorData) { 76 | var ee = escapeHtml(authorData.email); 77 | authorMarkup += ( 78 | '' + 79 | ("name" in authorData ? escapeHtml(authorData.name) : ee) + 80 | ''); 81 | } 82 | return authorMarkup; 83 | } 84 | 85 | function formatUrl(url) { 86 | var hu = escapeHtml(url); 87 | return hu.link(hu); 88 | } 89 | 90 | function compareByName(a, b) { 91 | if (a.name < b.name) 92 | return -1; 93 | if (a.name > b.name) 94 | return 1; 95 | return 0; 96 | } 97 | 98 | function fillTableRowForCmd(row, cmd, className) { 99 | var {name, names} = cmd; 100 | 101 | var checkBoxCell = $(''); 102 | (checkBoxCell.find("input") 103 | .val(cmd.id) 104 | .bind("change", (e) => { 105 | cmd.disabled = !e.target.checked; 106 | if (cmd.disabled) 107 | CmdUtils.disableCommand(cmd); 108 | else 109 | CmdUtils.enableCommand(cmd); 110 | }) 111 | [cmd.disabled ? "removeAttr" : "attr"]("checked", "checked")); 112 | 113 | var cmdElement = jQuery( 114 | '' + 116 | ('' + 117 | '' + escapeHtml(name) + '') + 118 | '' + 119 | (names.length < 2 ? "" : 120 | ('
    ' + 121 | "Synonims: " + 122 | ('' + 123 | escapeHtml(names.slice(1).join(", ")) + 124 | '') + 125 | '
    ')) + 126 | formatMetaData(cmd) + 127 | '
    ' + 128 | ''); 129 | 130 | if (cmd.oldAPI) { 131 | cmdElement.addClass("old-api").prepend( 132 | A("https://wiki.mozilla.org/Labs/Ubiquity/" + 133 | "Parser_2_API_Conversion_Tutorial", "OLD API", "badge")); 134 | } 135 | 136 | if (className) { 137 | checkBoxCell.addClass(className); 138 | cmdElement.addClass(className); 139 | } 140 | 141 | for (let key of ["description", "help"]) if (key in cmd) { 142 | let node = cmdElement[0].getElementsByClassName(key)[0]; 143 | try { node.innerHTML = cmd[key] } 144 | catch (e) { 145 | let msg = 'XML error in "' + key + '" of [ ' + cmd.name + ' ]'; 146 | console.error(msg); 147 | } 148 | } 149 | 150 | return row.append(checkBoxCell, cmdElement); 151 | } 152 | 153 | function insertNamespace(namespace, subtext, commands, table) { 154 | aRow = jQuery(""); 155 | feedElement = jQuery(''); 156 | fillTableCellForFeed(feedElement, namespace, subtext); 157 | aRow.append(feedElement); 158 | 159 | if (commands.length > 0) 160 | fillTableRowForCmd(aRow, commands.shift(), "topcell command"); 161 | 162 | table.append(aRow); 163 | 164 | if (commands.length > 0) { 165 | commands.forEach(c => { 166 | let aRow = jQuery(""); 167 | fillTableRowForCmd(aRow, c, "command"); 168 | table.append(aRow); 169 | }); 170 | } 171 | else 172 | aRow.append("  "); 173 | 174 | commandCategoryCount += 1; 175 | } 176 | 177 | function buildTable(customscripts) { 178 | let table = jQuery("#commands-and-feeds-table"); 179 | 180 | let builtinCommands = CmdUtils.CommandList.filter((c) => c.builtIn).sort(compareByName); 181 | let userCommands = CmdUtils.CommandList.filter((c) => !c.builtIn).sort(compareByName); 182 | let commandCount = builtinCommands.length + userCommands.length; 183 | 184 | jQuery("#num-commands").text(commandCount); 185 | 186 | const BUILTIN_AUTHOR = "by Ubiquity Authors"; 187 | 188 | function insertBuiltinNamespace(ns) { 189 | let namespaced = CmdUtils.CommandList.filter((c) => c.builtIn && c._namespace === ns).sort(compareByName); 190 | if (namespaced.length) 191 | insertNamespace(ns, BUILTIN_AUTHOR, namespaced, table); 192 | } 193 | 194 | insertBuiltinNamespace("Ubiquity"); 195 | insertBuiltinNamespace("Browser"); 196 | insertBuiltinNamespace("Utility"); 197 | insertBuiltinNamespace("Search"); 198 | insertBuiltinNamespace("Mail"); 199 | insertBuiltinNamespace("Syndication"); 200 | insertBuiltinNamespace("Translation"); 201 | insertBuiltinNamespace("Scrapyard"); 202 | 203 | if (CmdUtils.MORE_COMMANDS) 204 | insertBuiltinNamespace("More Commands"); 205 | 206 | builtinCommands = CmdUtils.CommandList.filter((c) => c.builtIn && !c._namespace).sort(compareByName); 207 | if (builtinCommands.length > 0) 208 | insertNamespace("Builtin Commands", BUILTIN_AUTHOR, builtinCommands, table); 209 | 210 | let userCommandsByCat = {}; 211 | 212 | for (let n in customscripts) { 213 | if (n !== "default") { 214 | let commands = CmdUtils.CommandList.filter((c) => c._namespace === n).sort(compareByName); 215 | userCommandsByCat[n] = commands; 216 | } 217 | } 218 | 219 | for (let n of Object.keys(userCommandsByCat).sort()) 220 | insertNamespace(n, '
    Open in editor', userCommandsByCat[n], table); 222 | 223 | var defaultCommands = CmdUtils.CommandList.filter((c) => c._namespace === "default").sort(compareByName); 224 | insertNamespace("Other Commands", 'Open in editor', 225 | defaultCommands, table); 226 | 227 | jQuery("#num-cats").text(commandCategoryCount); 228 | } 229 | 230 | jQuery(function onReady() { 231 | setupHelp("#show-hide-help", "#cmdlist-help-div"); 232 | CmdUtils.loadCustomScripts(customscripts => { 233 | buildTable(customscripts); 234 | }); 235 | }); 236 | -------------------------------------------------------------------------------- /res/options.css: -------------------------------------------------------------------------------- 1 | /* 2 | * CSS inspired by Hemingway: http://warpspire.com/hemingway 3 | */ 4 | 5 | body { 6 | background: #FFF; 7 | font-size: 13px; 8 | font-family: "Helvetica", Verdana, Arial, sans-serif; 9 | max-width: 900px; 10 | margin: 0px auto 8px auto; 11 | padding: 0 4px; 12 | color: #000; 13 | } 14 | 15 | #nav-container { 16 | margin-left: -40px; 17 | float: left; 18 | } 19 | 20 | li { 21 | padding: 3px; 22 | } 23 | 24 | #nav ul {} 25 | 26 | #nav li { 27 | background-color:#aaa; 28 | border-left:1px solid #CCCCCC; 29 | 30 | margin:0px; 31 | padding:0pt; 32 | 33 | float:left; 34 | height:45px; 35 | text-align:left; 36 | list-style-image:none; 37 | list-style-position:outside; 38 | list-style-type:none; 39 | width: 144px; 40 | } 41 | 42 | #nav a { 43 | padding: 5px; 44 | color: white; 45 | display: block; 46 | height: 100%; 47 | text-decoration: none; 48 | } 49 | 50 | #nav li:hover, #nav li.selected { 51 | background-color: #66bb00; 52 | } 53 | 54 | .page-tip { 55 | text-align: center; 56 | } 57 | 58 | .col-two { 59 | width: 225px; 60 | float: left; 61 | } 62 | 63 | .col-three { 64 | width: 315px; 65 | margin-right: 20px; 66 | float: left; 67 | } 68 | 69 | .col-four { 70 | width: 370px; 71 | float: left; 72 | } 73 | 74 | .col-five { 75 | width: 480px; 76 | margin-right: 20px; 77 | float: left; 78 | } 79 | 80 | .light, .meta { 81 | color: #999; 82 | } 83 | 84 | .head { 85 | font-weight: bold; 86 | background-color: white; 87 | text-align: left; 88 | color: grey; 89 | font-variant: small-caps; 90 | font-size: 14pt; 91 | padding-top: 10px; 92 | } 93 | 94 | .left { 95 | text-align: left; 96 | padding-left: 10px; 97 | } 98 | 99 | .large { 100 | font-size: 36pt; 101 | } 102 | 103 | h1{ 104 | color: #E21E26; 105 | font-variant: small-caps; 106 | } 107 | 108 | h4{ 109 | font-variant: small-caps; 110 | } 111 | 112 | h2{ 113 | border-top: 1px solid black; 114 | font-variant: small-caps; 115 | color: black; 116 | margin-top: 25px; 117 | padding: 10px 0; 118 | } 119 | 120 | h2.top { 121 | margin: 0px; 122 | } 123 | 124 | /* 125 | Removed for the time being since I changed 's to in the html sources 126 | which are also included into localizations, and mixing redundant tags is kind of ugly. 127 | I suggest just using custom classes for specific highlights from now on. I'll later 128 | tackle more more of the html and define new styles later. for 129 | green texting now. :) 130 | - Lech 131 | */ 132 | 133 | .highlight { 134 | color: #66bb00; 135 | font-style: normal; 136 | } 137 | 138 | #sort-container { 139 | padding: 10px; 140 | } 141 | 142 | .command, #skin-list .command { 143 | margin: 15px; 144 | margin-bottom: 20px; 145 | } 146 | 147 | .command .name, #skin-list .command .name { 148 | font-size: 15pt; 149 | } 150 | 151 | .command.not-loaded .name { 152 | color: #bbb; 153 | text-decoration: line-through; 154 | } 155 | 156 | .command .homepage, #skin-list .command .homepage { 157 | } 158 | 159 | .command .author, #skin-list .command .author { 160 | font-size: 90%; 161 | } 162 | 163 | .command .description, #skin-list .command .description { 164 | display: inline; 165 | font-size: 12pt; 166 | margin-left: 10px; 167 | color: #a7a7a7; 168 | } 169 | .command .synonyms { 170 | color: black; 171 | } 172 | 173 | #skin-list { 174 | padding: 0; 175 | } 176 | 177 | #skin-list .name { 178 | font-style: normal; 179 | } 180 | 181 | #skin-list .current-skin { 182 | color: blue; 183 | font-weight: 800; 184 | } 185 | 186 | .command .help { 187 | margin-top: 5px; 188 | color: #777; 189 | } 190 | 191 | 192 | 193 | #preview-image { 194 | border: 3px solid #000; 195 | padding: 2px; 196 | } 197 | 198 | a, a:visited { 199 | color: #CC6600; 200 | text-decoration: none; 201 | } 202 | 203 | a:hover { 204 | text-decoration: underline; 205 | } 206 | 207 | a[onclick], .sort-switch { 208 | cursor: pointer; 209 | } 210 | 211 | .sort-switch.selected { 212 | color: inherit; 213 | cursor: inherit; 214 | text-decoration: none; 215 | } 216 | 217 | .selected { 218 | 219 | } 220 | 221 | .error { 222 | color:#FF0000; 223 | } 224 | 225 | .alert { 226 | color:#FFFFFF; 227 | background:#FF0000; 228 | } 229 | 230 | .alert a { 231 | color:#FFFFFF; 232 | text-decoration: underline; 233 | } 234 | 235 | .action, .action:visited, .action:hover { 236 | color: #aaa; 237 | cursor: pointer; 238 | text-decoration: none; 239 | } 240 | 241 | .action:before { 242 | content: "["; 243 | } 244 | 245 | .action:after { 246 | content: "]"; 247 | } 248 | 249 | .command-feed .action { 250 | display: block; 251 | } 252 | 253 | .feed-updated { 254 | font-size: smaller; 255 | color: #009900; 256 | } 257 | 258 | .feed-date { 259 | font-size: 80%; 260 | } 261 | 262 | .notification { 263 | color: blue; 264 | font-variant: small-caps; 265 | font-size: 15pt; 266 | } 267 | 268 | div#editor-div iframe { 269 | border: 1px black solid !important; clear: both; margin: 1em auto; 270 | } 271 | 272 | /* Using FreakCERS's CSS from 273 | * http://users.skumleren.net/cers/examples/ubiquitybutton.html 274 | */ 275 | 276 | ul.button-list { 277 | list-style: none; 278 | } 279 | 280 | ul.button-list li { 281 | padding: 0px; 282 | } 283 | 284 | ul a.button { 285 | border: 1px #aaa solid; 286 | border-radius: 12px; 287 | background: #ddd url('chrome://ubiquity/skin/buttons/grad.png') 0 0 repeat-x; 288 | display: block; 289 | float: left; 290 | padding: 0 2em; 291 | height: 22px; 292 | color: black; 293 | text-decoration: none; 294 | text-align: center; 295 | margin-right: 15px; 296 | line-height: 22px; 297 | outline: none; 298 | } 299 | ul a:active.button { 300 | background-color: #cdcdcd; 301 | background-position: 0 -22px; 302 | } 303 | 304 | td.command-feed { 305 | font-size: 18px; 306 | } 307 | 308 | .command-feed .meta { 309 | font-size: 76%; 310 | } 311 | 312 | ul#command-feed-graveyard { 313 | list-style: none; 314 | margin: 0; 315 | padding: 0; 316 | } 317 | 318 | ul#command-feed-graveyard li { 319 | padding-bottom: .5em; 320 | } 321 | 322 | ul#command-feed-graveyard ul { 323 | list-style: none; 324 | padding-left: 20px; 325 | } 326 | 327 | ul#command-feed-graveyard ul:after { 328 | content: "."; 329 | display: block; 330 | height: 0; 331 | clear: both; 332 | visibility: hidden; 333 | } 334 | 335 | ul#command-feed-graveyard ul li { 336 | float: left; 337 | white-space: nowrap; 338 | padding-bottom: 0; 339 | } 340 | 341 | ul#command-feed-graveyard ul li:after { 342 | content: ","; 343 | } 344 | 345 | ul#command-feed-graveyard ul li:last-child:after { 346 | content: ""; 347 | } 348 | 349 | #commands-and-feeds-table td { 350 | vertical-align: top; 351 | } 352 | 353 | table { 354 | border-collapse: collapse; 355 | } 356 | 357 | th { 358 | font-variant: small-caps; 359 | font-size: 18pt; 360 | } 361 | 362 | td.topcell { 363 | border-top: 1px solid black; 364 | } 365 | 366 | .ubiq-tutorial { 367 | border-style:solid; 368 | border-color:green; 369 | padding: 2em; 370 | font-size: 120%; 371 | } 372 | 373 | div.ubiq-tutorial h2 { 374 | color: black; 375 | text-align: center; 376 | font-variant: normal; 377 | border: none; 378 | margin: 0; 379 | padding: 0; 380 | } 381 | 382 | .badge { 383 | border-width: 0; 384 | float: right; 385 | } 386 | 387 | .old-api > .badge { 388 | color: white; background-color: red; 389 | padding: 0 3px; border-radius: 6px; font: bold 10px/16px monospace; 390 | } 391 | 392 | .favicon { 393 | width: 16px; height: 16px; margin: 0 2px -1px 0; 394 | } 395 | 396 | #ubiq-debug-mode{ 397 | display: none; 398 | } 399 | 400 | #ubiq-debug-mode { 401 | color: #BF4545; 402 | top: 4px; 403 | position: relative; 404 | } 405 | 406 | .help { 407 | cursor: help; 408 | } 409 | 410 | .setting-table { 411 | font-size: 13px; 412 | } 413 | 414 | ul.syntax { 415 | margin-top: 0; 416 | margin-bottom: 0; 417 | padding-left: 20px; 418 | list-style: none; 419 | } 420 | 421 | ul.syntax li { 422 | padding: 0; 423 | } 424 | 425 | span.syntax { 426 | font-weight: 600; 427 | } 428 | 429 | span.arguments { 430 | font-weight: 600; 431 | display: inline-block; 432 | margin-top: 10px; 433 | } 434 | 435 | ul.arguments { 436 | margin-top: 0; 437 | margin-bottom: 0; 438 | padding-left: 20px; 439 | padding-top: 0; 440 | list-style: none; 441 | } 442 | 443 | .key-container { 444 | display: flex; 445 | } 446 | 447 | .key-value { 448 | flex: 1 1 auto; 449 | } 450 | 451 | .key-help { 452 | display: inline-block; 453 | flex: 0 1 auto; 454 | } 455 | 456 | .advanced { 457 | margin: 5px; 458 | } 459 | 460 | .since { 461 | color: white; 462 | background: #66bb00; 463 | padding: 2px; 464 | border-radius: 3px; 465 | font-weight: normal; 466 | font-size: 80%; 467 | margin-left: 10px; 468 | } -------------------------------------------------------------------------------- /lib/ace/ext-textarea.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}',t.$id="ace/theme/textmate";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}),ace.define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate"],function(e,t,n){"use strict";function a(e,t){for(var n in t)e.style[n]=t[n]}function f(e,t){if(e.type!="textarea")throw new Error("Textarea required!");var n=e.parentNode,i=document.createElement("div"),s=function(){var t="position:relative;";["margin-top","margin-left","margin-right","margin-bottom"].forEach(function(n){t+=n+":"+u(e,i,n)+";"});var n=u(e,i,"width")||e.clientWidth+"px",r=u(e,i,"height")||e.clientHeight+"px";t+="height:"+r+";width:"+n+";",t+="display:inline-block;",i.setAttribute("style",t)};r.addListener(window,"resize",s),s(),n.insertBefore(i,e.nextSibling);while(n!==document){if(n.tagName.toUpperCase()==="FORM"){var o=n.onsubmit;n.onsubmit=function(n){e.value=t(),o&&o.call(this,n)};break}n=n.parentNode}return i}function l(t,n,r){s.loadScript(t,function(){e([n],r)})}function c(e,t,n,r,i){function u(e){return e==="true"||e==1}var s=e.getSession(),o=e.renderer;return e.setDisplaySettings=function(t){t==null&&(t=n.style.display=="none"),t?(n.style.display="block",n.hideButton.focus(),e.on("focus",function r(){e.removeListener("focus",r),n.style.display="none"})):e.focus()},e.$setOption=e.setOption,e.$getOption=e.getOption,e.setOption=function(t,n){switch(t){case"mode":e.$setOption("mode","ace/mode/"+n);break;case"theme":e.$setOption("theme","ace/theme/"+n);break;case"keybindings":switch(n){case"vim":e.setKeyboardHandler("ace/keyboard/vim");break;case"emacs":e.setKeyboardHandler("ace/keyboard/emacs");break;default:e.setKeyboardHandler(null)}break;case"wrap":case"fontSize":e.$setOption(t,n);break;default:e.$setOption(t,u(n))}},e.getOption=function(t){switch(t){case"mode":return e.$getOption("mode").substr("ace/mode/".length);case"theme":return e.$getOption("theme").substr("ace/theme/".length);case"keybindings":var n=e.getKeyboardHandler();switch(n&&n.$id){case"ace/keyboard/vim":return"vim";case"ace/keyboard/emacs":return"emacs";default:return"ace"}break;default:return e.$getOption(t)}},e.setOptions(i),e}function h(e,n,i){function f(e,t,n,r){if(!n){e.push("");return}e.push("")}var s=null,o={mode:"Mode:",wrap:"Soft Wrap:",theme:"Theme:",fontSize:"Font Size:",showGutter:"Display Gutter:",keybindings:"Keyboard",showPrintMargin:"Show Print Margin:",useSoftTabs:"Use Soft Tabs:",showInvisibles:"Show Invisibles"},u={mode:{text:"Plain",javascript:"JavaScript",xml:"XML",html:"HTML",css:"CSS",scss:"SCSS",python:"Python",php:"PHP",java:"Java",ruby:"Ruby",c_cpp:"C/C++",coffee:"CoffeeScript",json:"json",perl:"Perl",clojure:"Clojure",ocaml:"OCaml",csharp:"C#",haxe:"haXe",svg:"SVG",textile:"Textile",groovy:"Groovy",liquid:"Liquid",Scala:"Scala"},theme:{clouds:"Clouds",clouds_midnight:"Clouds Midnight",cobalt:"Cobalt",crimson_editor:"Crimson Editor",dawn:"Dawn",gob:"Green on Black",eclipse:"Eclipse",idle_fingers:"Idle Fingers",kr_theme:"Kr Theme",merbivore:"Merbivore",merbivore_soft:"Merbivore Soft",mono_industrial:"Mono Industrial",monokai:"Monokai",pastel_on_dark:"Pastel On Dark",solarized_dark:"Solarized Dark",solarized_light:"Solarized Light",textmate:"Textmate",twilight:"Twilight",vibrant_ink:"Vibrant Ink"},showGutter:s,fontSize:{"10px":"10px","11px":"11px","12px":"12px","14px":"14px","16px":"16px"},wrap:{off:"Off",40:"40",80:"80",free:"Free"},keybindings:{ace:"ace",vim:"vim",emacs:"emacs"},showPrintMargin:s,useSoftTabs:s,showInvisibles:s},a=[];a.push("");for(var l in t.defaultOptions)a.push(""),a.push("");a.push("
    SettingValue
    ",o[l],""),f(a,l,u[l],i.getOption(l)),a.push("
    "),e.innerHTML=a.join("");var c=function(e){var t=e.currentTarget;i.setOption(t.title,t.value)},h=function(e){var t=e.currentTarget;i.setOption(t.title,t.checked)},p=e.getElementsByTagName("select");for(var d=0;dGmail.", 9 | help: `Syntax 10 |
      11 |
    • email this to email address [from account]
    • 12 |
    13 | Arguments
    14 |
      15 |
    • - this - mandatory keyword used as substitution for the selection, an arbitrary text may be used 16 | instead
    • 17 |
    • - email address - recipient's address: a valid email address
    • 18 |
    • - account - gmail account: {default, secondary}
    • 19 |
    20 | Example 21 |
      22 |
    • email this to user@example.com from secondary
    • 23 |
    `, 24 | builtIn: true, 25 | _namespace: "Mail", 26 | author: "g/christensen", 27 | icon: "/res/icons/email.png", 28 | preview: function(pblock, args, {Bin}) { 29 | let desc = "Send "; 30 | 31 | if (args.object && args.object.text) 32 | desc += "\"" + args.object.summary + "\" "; 33 | else 34 | desc += "empty message "; 35 | 36 | if (args.goal && args.goal.text) 37 | desc += "to <" + args.goal.text + "> "; 38 | 39 | if (args.source && args.source.text) 40 | desc += "from the " + args.source.text + " account."; 41 | else 42 | desc += "from the default account."; 43 | 44 | pblock.innerHTML = desc; 45 | }, 46 | execute: function(args, {Bin}) { 47 | let gmail = "https://mail.google.com/mail/u/" 48 | let gmail_compose = "?ui=2&view=cm"; 49 | 50 | let user = args.source && args.source.data? args.source.data: "0"; 51 | 52 | let url = gmail + user + "/" + gmail_compose; 53 | 54 | // if (args.instrument && args.instrument.text) 55 | // url += "&su=" + encodeURIComponent(args.object.text); 56 | 57 | if (args.object.text) 58 | url += "&body=" + encodeURIComponent(args.object.text); 59 | 60 | if (args.goal && args.goal.text) { 61 | url += "&to=" + encodeURIComponent(args.goal.text); 62 | Utils.makeBin(__STORED_EMAIL_UUID, bin => { 63 | let contacts = bin.contacts(); 64 | if (!contacts) 65 | contacts = []; 66 | 67 | if (!contacts.find(c => c.toLowerCase() === args.goal.text.toLowerCase())) { 68 | contacts.push(args.goal.text); 69 | bin.contacts(contacts); 70 | } 71 | }); 72 | } 73 | 74 | CmdUtils.addTab(url); 75 | } 76 | }); 77 | 78 | CmdUtils.CreateCommand({ 79 | name: "compose", 80 | uuid: "2C25DC63-66E0-493D-B750-D33B55999EDB", 81 | arguments: [{role: "object", nountype: noun_arb_text, label: "subject"}, 82 | {role: "goal", nountype: noun_type_contact, label: "contact"}, 83 | {role: "time", nountype: {default: 0, secondary: 1}, label: "account"} 84 | ], 85 | description: "Compose an empty email with the given subject using Gmail.", 86 | help: `Syntax 87 |
      88 |
    • compose message subject to email address [at account]
    • 89 |
    90 | Arguments
    91 |
      92 |
    • - email address - recipient's address: a valid email address
    • 93 |
    • - account - gmail account: {default, secondary}
    • 94 |
    95 | Example 96 |
      97 |
    • compose shopping list to user@example.com at secondary`, 98 | builtIn: true, 99 | _namespace: "Mail", 100 | author: "g/christensen", 101 | icon: "/res/icons/email.png", 102 | preview: function(pblock, args, {Bin}) { 103 | let desc = "Compose email to "; 104 | 105 | if (args.goal && args.goal.text) 106 | desc += "<" + args.goal.text + "> "; 107 | else 108 | desc += "nobody "; 109 | 110 | if (args.object && args.object.text) 111 | desc += "with subject: \"" + args.object.summary + "\" "; 112 | 113 | if (args.time && args.time.text) 114 | desc += "at the " + args.time.text + " account."; 115 | else 116 | desc += "at the default account."; 117 | 118 | pblock.innerHTML = desc; 119 | }, 120 | execute: function(args, {Bin}) { 121 | let gmail = "https://mail.google.com/mail/u/" 122 | let gmail_compose = "?ui=2&view=cm"; 123 | 124 | let user = args.time && args.time.data? args.time.data: "0"; 125 | 126 | let url = gmail + user + "/" + gmail_compose; 127 | 128 | if (args.object && args.object.text) 129 | url += "&su=" + encodeURIComponent(args.object.text); 130 | 131 | //if (args.object.text) 132 | // url += "&body=" + encodeURIComponent(args.object.text); 133 | 134 | if (args.goal && args.goal.text) { 135 | url += "&to=" + encodeURIComponent(args.goal.text); 136 | Utils.makeBin(__STORED_EMAIL_UUID, bin => { 137 | let contacts = bin.contacts(); 138 | if (!contacts) 139 | contacts = []; 140 | 141 | if (!contacts.find(c => c.toLowerCase() === args.goal.text.toLowerCase())) { 142 | contacts.push(args.goal.text); 143 | bin.contacts(contacts); 144 | } 145 | }); 146 | } 147 | 148 | CmdUtils.addTab(url); 149 | } 150 | }); 151 | 152 | CmdUtils.CreateCommand({ 153 | name: "forget-email", 154 | uuid: "C1B5C976-2BBE-4DD6-95E9-A65CC84E1B51", 155 | arguments: [{role: "object", nountype: noun_type_contact, label: "email"}], 156 | description: "Do not show the specified email in suggestions anymore.", 157 | builtIn: true, 158 | _namespace: "Mail", 159 | author: "g/christensen", 160 | icon: "/res/icons/forget-email.png", 161 | preview: function(pblock, args, {Bin}) { 162 | if (args.object.text) { 163 | pblock.innerHTML = "Forget " + args.object.text + "."; 164 | } 165 | else 166 | pblock.innerHTML = this.description; 167 | }, 168 | execute: function(args, {Bin}) { 169 | if (args.object.text) 170 | Utils.makeBin(__STORED_EMAIL_UUID, bin => { 171 | let contacts = bin.contacts(); 172 | if (!contacts) 173 | contacts = []; 174 | 175 | let em; 176 | if (em = contacts.find(c => {return c.toLowerCase() === args.object.text.toLowerCase()})) { 177 | contacts.splice(contacts.indexOf(em), 1); 178 | bin.contacts(contacts); 179 | } 180 | }); 181 | } 182 | }); 183 | 184 | CmdUtils.CreateCommand({ 185 | name: "forget-emails", 186 | uuid: "8CF164B7-1505-47BE-8DDD-7D1E3781ABF1", 187 | arguments: [{role: "object", nountype: noun_arb_text, label: "pattern"}], 188 | description: "Forget multiple emails at once.", 189 | help: `Syntax 190 |
        191 |
      • forget-emails {all | pattern}
      • 192 |
      193 | Arguments
      194 |
        195 |
      • - all - forget all emails
      • 196 |
      • - pattern - forget emails containing this string (may be a regular expression)
      • 197 |
      `, 198 | builtIn: true, 199 | _namespace: "Mail", 200 | author: "g/christensen", 201 | icon: "/res/icons/forget-email.png", 202 | preview: function(pblock, args, {Bin}) { 203 | if (args.object.text) { 204 | if (args.object.text.toLowerCase() === "all") 205 | pblock.innerHTML = "Forget all emails."; 206 | else 207 | pblock.innerHTML = "Forget all emails containing \"" + args.object.text + "\"."; 208 | } 209 | else 210 | pblock.innerHTML = this.description; 211 | }, 212 | execute: function(args, {Bin}) { 213 | if (args.object.text) { 214 | Utils.makeBin(__STORED_EMAIL_UUID, bin => { 215 | let contacts = bin.contacts(); 216 | if (!contacts) 217 | contacts = []; 218 | 219 | if (args.object.text.toLowerCase() === "all") 220 | bin.contacts([]); 221 | else { 222 | let matcher = RegExp(args.object.text, "i"); 223 | bin.contacts(contacts.filter(c => !c.match(matcher))); 224 | } 225 | }); 226 | } 227 | } 228 | }); -------------------------------------------------------------------------------- /lib/ace/ext-searchbox.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=e("../lib/lang"),s=e("../lib/event"),o='.ace_search {background-color: #ddd;color: #666;border: 1px solid #cbcbcb;border-top: 0 none;overflow: hidden;margin: 0;padding: 4px 6px 0 4px;position: absolute;top: 0;z-index: 99;white-space: normal;}.ace_search.left {border-left: 0 none;border-radius: 0px 0px 5px 0px;left: 0;}.ace_search.right {border-radius: 0px 0px 0px 5px;border-right: 0 none;right: 0;}.ace_search_form, .ace_replace_form {margin: 0 20px 4px 0;overflow: hidden;line-height: 1.9;}.ace_replace_form {margin-right: 0;}.ace_search_form.ace_nomatch {outline: 1px solid red;}.ace_search_field {border-radius: 3px 0 0 3px;background-color: white;color: black;border: 1px solid #cbcbcb;border-right: 0 none;outline: 0;padding: 0;font-size: inherit;margin: 0;line-height: inherit;padding: 0 6px;min-width: 17em;vertical-align: top;min-height: 1.8em;box-sizing: content-box;}.ace_searchbtn {border: 1px solid #cbcbcb;line-height: inherit;display: inline-block;padding: 0 6px;background: #fff;border-right: 0 none;border-left: 1px solid #dcdcdc;cursor: pointer;margin: 0;position: relative;color: #666;}.ace_searchbtn:last-child {border-radius: 0 3px 3px 0;border-right: 1px solid #cbcbcb;}.ace_searchbtn:disabled {background: none;cursor: default;}.ace_searchbtn:hover {background-color: #eef1f6;}.ace_searchbtn.prev, .ace_searchbtn.next {padding: 0px 0.7em}.ace_searchbtn.prev:after, .ace_searchbtn.next:after {content: "";border: solid 2px #888;width: 0.5em;height: 0.5em;border-width: 2px 0 0 2px;display:inline-block;transform: rotate(-45deg);}.ace_searchbtn.next:after {border-width: 0 2px 2px 0 ;}.ace_searchbtn_close {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;border-radius: 50%;border: 0 none;color: #656565;cursor: pointer;font: 16px/16px Arial;padding: 0;height: 14px;width: 14px;top: 9px;right: 7px;position: absolute;}.ace_searchbtn_close:hover {background-color: #656565;background-position: 50% 100%;color: white;}.ace_button {margin-left: 2px;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;overflow: hidden;opacity: 0.7;border: 1px solid rgba(100,100,100,0.23);padding: 1px;box-sizing: border-box!important;color: black;}.ace_button:hover {background-color: #eee;opacity:1;}.ace_button:active {background-color: #ddd;}.ace_button.checked {border-color: #3399ff;opacity:1;}.ace_search_options{margin-bottom: 3px;text-align: right;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;clear: both;}.ace_search_counter {float: left;font-family: arial;padding: 0 8px;}',u=e("../keyboard/hash_handler").HashHandler,a=e("../lib/keys"),f=999;r.importCssString(o,"ace_searchbox");var l=function(e,t,n){var i=r.createElement("div");r.buildDom(["div",{"class":"ace_search right"},["span",{action:"hide","class":"ace_searchbtn_close"}],["div",{"class":"ace_search_form"},["input",{"class":"ace_search_field",placeholder:"Search for",spellcheck:"false"}],["span",{action:"findPrev","class":"ace_searchbtn prev"},"\u200b"],["span",{action:"findNext","class":"ace_searchbtn next"},"\u200b"],["span",{action:"findAll","class":"ace_searchbtn",title:"Alt-Enter"},"All"]],["div",{"class":"ace_replace_form"},["input",{"class":"ace_search_field",placeholder:"Replace with",spellcheck:"false"}],["span",{action:"replaceAndFindNext","class":"ace_searchbtn"},"Replace"],["span",{action:"replaceAll","class":"ace_searchbtn"},"All"]],["div",{"class":"ace_search_options"},["span",{action:"toggleReplace","class":"ace_button",title:"Toggle Replace mode",style:"float:left;margin-top:-2px;padding:0 5px;"},"+"],["span",{"class":"ace_search_counter"}],["span",{action:"toggleRegexpMode","class":"ace_button",title:"RegExp Search"},".*"],["span",{action:"toggleCaseSensitive","class":"ace_button",title:"CaseSensitive Search"},"Aa"],["span",{action:"toggleWholeWords","class":"ace_button",title:"Whole Word Search"},"\\b"],["span",{action:"searchInSelection","class":"ace_button",title:"Search In Selection"},"S"]]],i),this.element=i.firstChild,this.setSession=this.setSession.bind(this),this.$init(),this.setEditor(e),r.importCssString(o,"ace_searchbox",e.container)};(function(){this.setEditor=function(e){e.searchBox=this,e.renderer.scroller.appendChild(this.element),this.editor=e},this.setSession=function(e){this.searchRange=null,this.$syncOptions(!0)},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOption=e.querySelector("[action=searchInSelection]"),this.replaceOption=e.querySelector("[action=toggleReplace]"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field"),this.searchCounter=e.querySelector(".ace_search_counter")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;s.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),s.stopPropagation(e)}),s.addListener(e,"click",function(e){var n=e.target||e.srcElement,r=n.getAttribute("action");r&&t[r]?t[r]():t.$searchBarKb.commands[r]&&t.$searchBarKb.commands[r].exec(t),s.stopPropagation(e)}),s.addCommandKeyListener(e,function(e,n,r){var i=a.keyCodeToString(r),o=t.$searchBarKb.findKeyCommand(n,i);o&&o.exec&&(o.exec(t),s.stopEvent(e))}),this.$onChange=i.delayedCall(function(){t.find(!1,!1)}),s.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),s.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),s.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new u([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new u,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e.replaceOption.checked=!1,e.$syncOptions(),e.searchInput.focus()},"Ctrl-H|Command-Option-F":function(e){if(e.editor.getReadOnly())return;e.replaceOption.checked=!0,e.$syncOptions(),e.replaceInput.focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},"Alt-Return":function(e){e.activeInput==e.replaceInput&&e.replaceAll(),e.findAll()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}},{name:"toggleReplace",exec:function(e){e.replaceOption.checked=!e.replaceOption.checked,e.$syncOptions()}},{name:"searchInSelection",exec:function(e){e.searchOption.checked=!e.searchRange,e.setSearchRange(e.searchOption.checked&&e.editor.getSelectionRange()),e.$syncOptions()}}]),this.setSearchRange=function(e){this.searchRange=e,e?this.searchRangeMarker=this.editor.session.addMarker(e,"ace_active-line"):this.searchRangeMarker&&(this.editor.session.removeMarker(this.searchRangeMarker),this.searchRangeMarker=null)},this.$syncOptions=function(e){r.setCssClass(this.replaceOption,"checked",this.searchRange),r.setCssClass(this.searchOption,"checked",this.searchOption.checked),this.replaceOption.textContent=this.replaceOption.checked?"-":"+",r.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),r.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),r.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked);var t=this.editor.getReadOnly();this.replaceOption.style.display=t?"none":"",this.replaceBox.style.display=this.replaceOption.checked&&!t?"":"none",this.find(!1,!1,e)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t,n){var i=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked,preventScroll:n,range:this.searchRange}),s=!i&&this.searchInput.value;r.setCssClass(this.searchBox,"ace_nomatch",s),this.editor._emit("findSearchBox",{match:!s}),this.highlight(),this.updateCounter()},this.updateCounter=function(){var e=this.editor,t=e.$search.$options.re,n=0,r=0;if(t){var i=this.searchRange?e.session.getTextRange(this.searchRange):e.getValue(),s=e.session.doc.positionToIndex(e.selection.anchor);this.searchRange&&(s-=e.session.doc.positionToIndex(this.searchRange.start));var o=t.lastIndex=0,u;while(u=t.exec(i)){n++,o=u.index,o<=s&&r++;if(n>f)break;if(!u[0]){t.lastIndex=o+=1;if(o>=i.length)break}}}this.searchCounter.textContent=r+" of "+(n>f?f+"+":n)},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.findAll=function(){var e=this.editor.findAll(this.searchInput.value,{regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),t=!e&&this.searchInput.value;r.setCssClass(this.searchBox,"ace_nomatch",t),this.editor._emit("findSearchBox",{match:!t}),this.highlight(),this.hide()},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.active=!1,this.setSearchRange(null),this.editor.off("changeSession",this.setSession),this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.active=!0,this.editor.on("changeSession",this.setSession),this.element.style.display="",this.replaceOption.checked=t,e&&(this.searchInput.value=e),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb),this.$syncOptions(!0)},this.isFocused=function(){var e=document.activeElement;return e==this.searchInput||e==this.replaceInput}}).call(l.prototype),t.SearchBox=l,t.Search=function(e,t){var n=e.searchBox||new l(e);n.show(e.session.getTextRange(),t)}}); (function() { 2 | ace.require(["ace/ext/searchbox"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /parser/nounutils.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Ubiquity. 15 | * 16 | * The Initial Developer of the Original Code is Mozilla. 17 | * Portions created by the Initial Developer are Copyright (C) 2007 18 | * the Initial Developer. All Rights Reserved. 19 | * 20 | * Contributor(s): 21 | * Atul Varma 22 | * Aza Raskin 23 | * Jono DiCarlo 24 | * Maria Emerson 25 | * Blair McBride 26 | * Abimanyu Raja 27 | * Michael Yoshitaka Erlewine 28 | * Satoshi Murakami 29 | * 30 | * Alternatively, the contents of this file may be used under the terms of 31 | * either the GNU General Public License Version 2 or later (the "GPL"), or 32 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 33 | * in which case the provisions of the GPL or the LGPL are applicable instead 34 | * of those above. If you wish to allow use of your version of this file only 35 | * under the terms of either the GPL or the LGPL, and not to allow others to 36 | * use your version of this file under the terms of the MPL, indicate your 37 | * decision by deleting the provisions above and replace them with the notice 38 | * and other provisions required by the GPL or the LGPL. If you do not delete 39 | * the provisions above, a recipient may use your version of this file under 40 | * the terms of any one of the MPL, the GPL or the LGPL. 41 | * 42 | * ***** END LICENSE BLOCK ***** */ 43 | 44 | // = NounUtils = 45 | // 46 | // A library of noun related utilities. 47 | // {{{CmdUtils}}} inherits them all. 48 | 49 | var NounUtils = {}; 50 | 51 | (function () { 52 | 53 | // === {{{ NounUtils.NounType(label, expected, defaults) }}} === 54 | // 55 | // Constructor of a noun type that accepts a specific set of inputs. 56 | // See {{{NounType._from*}}} methods for details 57 | // (but do not use them directly). 58 | // 59 | // {{{label}}} is an optional string specifying default label of the nountype. 60 | // 61 | // {{{expected}}} is the instance of {{{Array}}}, {{{Object}}} or {{{RegExp}}}. 62 | // The array can optionally be a space-separeted string. 63 | // 64 | // {{{defaults}}} is an optional array or space-separated string 65 | // of default inputs. 66 | 67 | NounType = function (label, expected, defaults) { 68 | if (!(this instanceof NounType)) 69 | return new NounType(label, expected, defaults); 70 | 71 | if (typeof label !== "string") 72 | [label, expected, defaults] = ["?", label, expected]; 73 | 74 | if (typeof expected.suggest === "function") return expected; 75 | 76 | var maybe_qw = o => typeof o == "string" ? o.match(/\S+/g) || [] : o 77 | expected = maybe_qw(expected); 78 | defaults = maybe_qw(defaults); 79 | 80 | var maker = NounType["_from" + Utils.classOf(expected)]; 81 | for (let [k, v] of Object.entries(maker(expected))) this[k] = v; 82 | this.suggest = maker.suggest; 83 | this.label = label; 84 | this.noExternalCalls = true; 85 | this.cacheTime = -1; 86 | 87 | 88 | if (this.id) { 89 | let s1 = expected instanceof RegExp? expected.toString(): JSON.stringify(expected); 90 | let s2 = defaults instanceof RegExp? defaults.toString(): JSON.stringify(defaults); 91 | 92 | this.id += Utils.hash(s1 + s2); 93 | 94 | } 95 | if (defaults) { 96 | // [[a], [b, c], ...] => [a].concat([b, c], ...) => [a, b, c, ...] 97 | this.default = 98 | Array.prototype.concat.apply(0, defaults.map(d => this.suggest(d))); 99 | } 100 | }; 101 | 102 | CmdUtils.NounType = NounUtils.NounType = NounType; 103 | 104 | // ** {{{ NounUtils.NounType._fromArray(words) }}} ** 105 | // 106 | // Creates a noun type that accepts a finite list of specific words 107 | // as the only valid inputs. Those words will be suggested as {{{text}}}s. 108 | // 109 | // {{{words}}} is the array of words. 110 | 111 | NounType._fromArray = words => ({ 112 | id: "#na_", 113 | name: words.slice(0, 2) + (words.length > 2 ? ",..." : ""), 114 | _list: words.map(w => NounUtils.makeSugg(w)), 115 | }); 116 | 117 | // ** {{{ NounUtils.NounType._fromObject(dict) }}} ** 118 | // 119 | // Creates a noun type from the given key:value pairs, the key being 120 | // the {{{text}}} attribute of its suggest and the value {{{data}}}. 121 | // 122 | // {{{dict}}} is the object of text:data pairs. 123 | 124 | NounType._fromObject = function NT_Object(dict) { 125 | var list = Object.keys(dict).map(key => NounUtils.makeSugg(key, null, dict[key])); 126 | return { 127 | name: list.slice(0, 2).map(s => s.text) + 128 | (list.length > 2 ? ",..." : ""), 129 | _list: list, 130 | }; 131 | }; 132 | 133 | NounType._fromArray.suggest = NounType._fromObject.suggest = 134 | function NT_suggest(text) { 135 | return NounUtils.grepSuggs(text, this._list) 136 | } 137 | 138 | // ** {{{ NounUtils.NounType._fromRegExp(regexp) }}} ** 139 | // 140 | // Creates a noun type from the given regular expression object 141 | // and returns it. The {{{data}}} attribute of the noun type is 142 | // the {{{match}}} object resulting from the regular expression 143 | // match. 144 | // 145 | // {{{regexp}}} is the RegExp object that checks inputs. 146 | 147 | NounType._fromRegExp = regexp => ({ 148 | id: "#nr_", 149 | name: regexp + "", 150 | rankLast: regexp.test(""), 151 | _regexp: RegExp( 152 | regexp.source, 153 | ["g"[regexp.global - 1] 154 | , "i"[regexp.ignoreCase - 1] 155 | , "m"[regexp.multiline - 1] 156 | , "y"[regexp.sticky - 1] 157 | ].join('')), 158 | }); 159 | NounType._fromRegExp.suggest = function NT_RE_suggest(text, html, cb, 160 | selectionIndices) { 161 | var match = text.match(this._regexp); 162 | if (!match) return []; 163 | // ToDo: how to score global match 164 | var score = "index" in match ? NounUtils.matchScore(match) : 1; 165 | return [NounUtils.makeSugg(text, html, match, score, selectionIndices)]; 166 | }; 167 | 168 | // === {{{ NounUtils.matchScore(match) }}} === 169 | // 170 | // Calculates the score for use in suggestions from 171 | // a result array ({{{match}}}) of {{{RegExp#exec}}}. 172 | 173 | const SCORE_BASE = 0.3; 174 | const SCORE_LENGTH = 0.25; 175 | const SCORE_INDEX = 1 - SCORE_BASE - SCORE_LENGTH; 176 | 177 | CmdUtils.matchScore = NounUtils.matchScore = function matchScore(match) { 178 | var inLen = match.input.length; 179 | return (SCORE_BASE + 180 | SCORE_LENGTH * Math.sqrt(match[0].length / inLen) + 181 | SCORE_INDEX * (1 - match.index / inLen)); 182 | } 183 | 184 | // === {{{NounUtils.makeSugg(text, html, data, score, selectionIndices)}}} === 185 | // 186 | // Creates a suggestion object, filling in {{{text}}} and {{{html}}} if missing 187 | // and constructing {{{summary}}} from {{{text}}} and {{{selectionIndices}}}. 188 | // At least one of {{{text}}}, {{{html}}} or {{{data}}} is required. 189 | // 190 | // {{{text}}} can be any string. 191 | // 192 | // {{{html}}} must be a valid HTML string. 193 | // 194 | // {{{data}}} can be any value. 195 | // 196 | // {{{score}}} is an optional float number representing 197 | // the score of the suggestion. Defaults to {{{1.0}}}. 198 | // 199 | // {{{selectionIndices}}} is an optional array containing the start and end 200 | // indices of selection within {{{text}}}. 201 | 202 | CmdUtils.makeSugg = NounUtils.makeSugg = function makeSugg(text, html, data, score, selectionIndices) { 203 | if (text == null && html == null && arguments.length < 3) 204 | // all inputs empty! There is no suggestion to be made. 205 | return null; 206 | 207 | // Shift the argument if appropriate: 208 | if (typeof score === "object") { 209 | selectionIndices = score; 210 | score = null; 211 | } 212 | 213 | // Fill in missing fields however we can: 214 | if (text != null) text += ""; 215 | if (html != null) html += ""; 216 | if (!text && data != null) 217 | text = data.toString(); 218 | if (!html && text >= "") 219 | html = Utils.escapeHtml(text); 220 | if (!text && html >= "") 221 | text = html.replace(/<[^>]*>/g, ""); 222 | 223 | // Create a summary of the text: 224 | var snippetLength = 35; 225 | var summary = (text.length > snippetLength 226 | ? text.slice(0, snippetLength - 1) + "\u2026" 227 | : text); 228 | 229 | // If the input comes all or in part from a text selection, 230 | // we'll stick some html tags into the summary so that the part 231 | // that comes from the text selection can be visually marked in 232 | // the suggestion list. 233 | var [start, end] = selectionIndices || []; 234 | summary = ( 235 | start < end 236 | ? (Utils.escapeHtml(summary.slice(0, start)) + 237 | "" + 238 | Utils.escapeHtml(summary.slice(start, end)) + 239 | "" + 240 | Utils.escapeHtml(summary.slice(end))) 241 | : Utils.escapeHtml(summary)); 242 | 243 | return { 244 | text: text, html: html, data: data, 245 | summary: summary, score: score || 1 246 | }; 247 | } 248 | 249 | // === {{{ NounUtils.grepSuggs(input, suggs, key) }}} === 250 | // 251 | // A helper function to grep a list of suggestion objects by user input. 252 | // Returns an array of filtered suggetions, each of them assigned {{{score}}} 253 | // calculated by {{{NounUtils.matchScore()}}}. 254 | // 255 | // {{{input}}} is a string that filters the list. 256 | // 257 | // {{{suggs}}} is an array or dictionary of suggestion objects. 258 | // 259 | // {{{key}}} is an optional string to specify the target property 260 | // to match with. Defaults to {{{"text"}}}. 261 | 262 | CmdUtils.grepSuggs = NounUtils.grepSuggs = function grepSuggs(input, suggs, key) { 263 | if (!input) return []; 264 | if (key == null) 265 | key = "text"; 266 | 267 | var re = Utils.regexp(input, "i"), match; 268 | 269 | var result = []; 270 | for (let sugg of suggs) { 271 | if ((match = re.exec(sugg[key]))) { 272 | var new_sugg = Object.assign({}, sugg); 273 | new_sugg.score = NounUtils.matchScore(match); 274 | result.push(new_sugg); 275 | } 276 | } 277 | 278 | // var result = suggs.map(sugg => { 279 | // if ((match = re.exec(sugg[key]))) { 280 | // sugg.score = matchScore(match); 281 | // } 282 | // else 283 | // sugg.score = 0; 284 | // return sugg; 285 | // }) 286 | 287 | return result.sort(byScoreDescending); 288 | }; 289 | 290 | let byScoreDescending = (a, b) => b.score - a.score 291 | 292 | })(); -------------------------------------------------------------------------------- /lib/ace/ext-options.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../../lib/dom"),i="#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 100000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {vertical-align: middle;}.ace_optionsMenuEntry button[ace_selected_button=true] {background: #e7e7e7;box-shadow: 1px 0px 2px 0px #adadad inset;border-color: #adadad;}.ace_optionsMenuEntry button {background: white;border: 1px solid lightgray;margin: 0px;}.ace_optionsMenuEntry button:hover{background: #f0f0f0;}";r.importCssString(i),n.exports.overlayPage=function(t,n,i,s,o,u){function l(e){e.keyCode===27&&a.click()}i=i?"top: "+i+";":"",o=o?"bottom: "+o+";":"",s=s?"right: "+s+";":"",u=u?"left: "+u+";":"";var a=document.createElement("div"),f=document.createElement("div");a.style.cssText="margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);",a.addEventListener("click",function(){document.removeEventListener("keydown",l),a.parentNode.removeChild(a),t.focus(),a=null}),document.addEventListener("keydown",l),f.style.cssText=i+s+o+u,f.addEventListener("click",function(e){e.stopPropagation()});var c=r.createElement("div");c.style.position="relative";var h=r.createElement("div");h.className="ace_closeButton",h.addEventListener("click",function(){a.click()}),c.appendChild(h),f.appendChild(c),f.appendChild(n),a.appendChild(f),document.body.appendChild(a),t.blur()}}),ace.define("ace/ext/modelist",["require","exports","module"],function(e,t,n){"use strict";function i(e){var t=a.text,n=e.split(/[\/\\]/).pop();for(var i=0;i