Last active
October 6, 2016 04:09
-
-
Save satyr/99201 to your computer and use it in GitHub Desktop.
Builds a text (from the page title etc.) and sends it to your clipboard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const | |
H = Utils.escapeHtml, | |
Aliases = { | |
t: { | |
help: 'title', | |
get text(){ return info().title }, | |
}, | |
u: { | |
help: 'URL', | |
get text(){ return info().url }, | |
}, | |
a: { | |
help: 'title and URL as link tag', | |
get text(){ | |
var _ = info() | |
return '<a href="'+ H(_.url) +'">'+ H(_.title) +'</a>' | |
}, | |
}, | |
f: { | |
help: 'favicon URL', | |
get text(){ | |
var doc = CmdUtils.getDocument() | |
var lnk = doc.querySelector('link[rel~=icon]') | |
return lnk ? lnk.href : 'http://'+ doc.location.hostname +'/favicon.ico' | |
}, | |
}, | |
F: { | |
help: 'favicon as data:image/png', | |
get text(){ return src2du(favicon()) }, | |
}, | |
c: { | |
help: 'clipboard', | |
get text(){ return Utils.clipboard.text }, | |
}, | |
s: { | |
help: 'selected text', | |
get text(){ return CmdUtils.getSelection() }, | |
}, | |
h: { | |
help: 'selection as HTML', | |
get text(){ return CmdUtils.getHtmlSelection() }, | |
}, | |
q: { | |
help: 'selection as blockquote', | |
get text(){ | |
var _ = info() | |
return '<blockquote cite="'+ H(_.url) +'" title="'+ H(_.title) +'">'+ | |
CmdUtils.getHtmlSelection() +'</blockquote>' | |
} | |
}, | |
i: { | |
help: 'selected image (or "1x1 transparent" if none) as data:image/png', | |
get text(){ | |
let img = imgnow() | |
return img | |
? img2du(img) | |
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCA'+ | |
'QAAAC1HAwCAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII' | |
} | |
}, | |
j: { | |
help: 'snapshot of focused window as data:image/jpeg', | |
get text(){ return snapshot('jpeg') }, | |
}, | |
p: { | |
help: 'snapshot of focused window as data:image/png', | |
get text(){ return snapshot('png') }, | |
}, | |
M: { | |
help: 'selection as MD5 hash', | |
get text(){ | |
return Utils.computeCryptoHash('MD5', CmdUtils.getSelection()) | |
}, | |
}, | |
S: { | |
help: 'selection as SHA1 hash', | |
get text(){ | |
return Utils.computeCryptoHash('SHA1', CmdUtils.getSelection()) | |
}, | |
}, | |
d: { | |
help: 'current datetime in RFC3399 format', | |
get text(){ return new Date().toISOString() }, | |
}, | |
U: { | |
help: 'URL as JSON', | |
get text(){ | |
var o = info(), a = context.focusedWindow.document.createElement('a') | |
a.href = o.url | |
for(let p of ['protocol', 'host', 'pathname', 'search', 'hash']) | |
o[p] = a[p] | |
o.query = o.search ? Utils.urlToParams(o.search) : {} | |
return JSON.stringify(o, null, 2) | |
}, | |
}, | |
n: { | |
help: 'line feed character', | |
text: Utils.OS === 'WINNT' ? '\r\n' : '\n', | |
}, | |
T: { | |
help: 'tab character', | |
text: '\t', | |
}, | |
/* | |
_: { | |
help: '', | |
get text(){}, | |
}, | |
*/ | |
}, | |
REA = RegExp('['+ Object.keys(Aliases).join('') +']', 'g'), | |
AliasHelp = | |
'<ul style="list-style:none; margin:0.4ex 0.2em; padding:0">[ Aliases ]'+ | |
[for(k of Object.keys(Aliases)) | |
'<li><tt><b>'+ k +'</b>:</tt>'+ H(Aliases[k].help) +'</li>' | |
].join('') + '</ul>', | |
Listers = { | |
'a@href': { | |
help: H('<a href="...">') +' in page', | |
text: a => a.href, | |
html: a => ax(a.href, a.textContent), | |
*[Symbol.iterator](){ yield* uni(qsa('a[href], area[href]'), 'href') }, | |
}, | |
'link@href': { | |
help: H('<link href="...">') +' in page', | |
text: l => l.href, | |
html: function(l){ | |
let t = l.rel || l.type | |
return '['+ (/\b(?:rss|atom|xml|icon)\b/i.exec(t) || t) +'] '+ | |
ax(l.href, l.title) | |
}, | |
*[Symbol.iterator](){ yield* uni(qsa('link[href]'), 'href') }, | |
}, | |
'img@src': { | |
help: H('<img src="...">') +' in page', | |
text: i => i.src, | |
html: i => '<img src="'+ H(i.src) +'" style="max-width:90%"/>', | |
*[Symbol.iterator](){ yield* uni(qsa(ImgQ), 'src') }, | |
}, | |
'embed@src': { | |
help: H('<embed src="...">') +' in page', | |
text: e => e.src, | |
html: e => | |
'<embed src="'+ H(t) +'" height="200" wmode="opaque"/>', | |
*[Symbol.iterator](){ yield* uni(qsa('embed[src]'), 'src') }, | |
css: 'embed {vertical-align:top} li {height:200px}', | |
}, | |
tabs: { | |
help: 'tab title/URL', | |
text: d => d.title +'\n'+ d.location.href, | |
html: d => ax(d.location.href, d.title), | |
*[Symbol.iterator](){ for(let t of Utils.tabs) yield t.document }, | |
}, | |
/* | |
_: { | |
help: '', | |
text: function() , | |
html: function() , | |
*[Symbol.iterator](){}, | |
}, | |
*/ | |
}, | |
ListerSuggs = Object.keys(Listers).map((k, i) => ({ | |
text: k, data: Listers[k], summary: k, index: i | |
})), | |
Images = { | |
selected: imgnow, | |
favicon: favicon, | |
snapshot: () => snapshot('png'), | |
}, | |
ImgQ = 'img, input[type=image]', | |
DUCache = {'': 'data:,...'}; | |
[{ | |
name: 'copy', | |
argument: { | |
name: 'copy format', | |
label: 'format', | |
rankLast: true, | |
default: function nt_copy_default(){ | |
return this._sugg(Bin.lastInput() || '') | |
}, | |
suggest: function nt_copy_suggest(txt, htm, cb, sx){ | |
return txt && !sx ? [this._sugg(Bin.lastInput(txt))] : [] | |
}, | |
_sugg: function(t){ | |
return {text: t, summary: t.replace(REA, this._mark)} | |
}, | |
_mark: $ => '<u>'+ H($) +'</u>', | |
}, | |
description: | |
'Collects various informations into a text and sends it to clipboard, ' + | |
'using single character aliases.', | |
help: | |
'Try: <ul><li>'+ | |
'"copy tnu" to copy the page title and url separated by a newline'+ | |
'</li><li>'+ | |
'"copy cs" to append the selection to clipboard'+ | |
'</li></ul>etc.'+ | |
AliasHelp, | |
execute: function copy_execute({object: {text}}){ | |
copy1(parse(text), this); | |
}, | |
preview: function copy_preview(pb, {object: {text}}){ | |
pb.innerHTML = | |
'<pre>'+ (H(parse(text)) || '<em>empty</em>') +'</pre>' + AliasHelp | |
}, | |
previewDelay: 200, | |
}, { | |
name: 'copy all', | |
arguments: { | |
object: { | |
name: 'copy list', | |
label: '...', | |
default: function nt_ca_default(){ | |
return ListerSuggs[Bin.lastSelection()] | |
}, | |
suggest: function nt_ca_suggest(txt, htm, cb, sx){ | |
if(!txt || (sx || 0)[1]) return []; | |
var ss = CmdUtils.grepSuggs(txt, ListerSuggs); | |
if(ss.length) Bin.lastSelection(ss[0].index); | |
return ss; | |
}, | |
}, | |
modifier_filter: noun_arb_text, | |
}, | |
description: | |
'Copies a newline separated list of all ... to clipboard.', | |
help: '<dl>'+ | |
[for (k of Object.keys(Listers)) | |
'<dt><b><code>'+ k +'</code></b></dt><dd>'+ H(Listers[k].help) +'</dd>' | |
].join('') +'</dl>', | |
execute: function copyall_execute( | |
{object: {text: what, data: lister}, modifier: {text: filter}}){ | |
if(!lister) return; | |
var list = pick(lister, filter); | |
if(!list.length) return; | |
var r = list.map(lister.text).join('\n'); | |
CmdUtils.copyToClipboard(r); | |
displayMessage( | |
what +' x '+ list.length + ' ('+ r.length.toLocaleString() +' chars)', | |
this); | |
}, | |
preview: function copyall_preview( | |
pb, {object: {data: lister}, modifier: {text: filter}}){ | |
if(!lister) return void this.previewDefault(pb) | |
var list = pick(lister, filter) | |
if(!list.length) return void(pb.innerHTML = '<code><b>[]</b></code>') | |
var me = this | |
CmdUtils.previewList( | |
pb, list.map(lister.html), | |
function copyall_one(i){ copy1(lister.text(list[i]), me) }, | |
this._css + (lister.css || "")) | |
}, | |
previewDelay: 250, | |
_css: '.uri {display:block; font-size:88%}', | |
}, { | |
name: 'copy image', | |
description: 'Copies an image as bitmap.', | |
help: 'Targets:'+ | |
[for(k of Object.keys(Images)) ' <code><b>'+ k +'</b></code>'], | |
argument: CmdUtils.NounType('target', Images), | |
execute: function copyimg_execute(args){ | |
var [src, img] = this._get(args); | |
if(!src) return; | |
Utils.clipboard.image = img; | |
displayMessage({text: src}, this); | |
}, | |
preview: function copyimg_preview(pb, args){ | |
var [src] = this._get(args); | |
if(!src) return void this.previewDefault(pb); | |
var hs = H(src) | |
pb.innerHTML = | |
'<img src="'+ hs +'"><br><code><a href="'+ hs +'">'+ hs | |
}, | |
_get: function copyimg_get({object: {data}}){ | |
var img = data ? data() : imgnow() || favicon(); | |
return [img && (img.src || img), img]; | |
}, | |
}].forEach(function CopyCommand(o){ | |
o.icon = 'chrome://ubiquity/skin/icons/convert.png'; | |
CmdUtils.CreateCommand(o); | |
}); | |
function copy1(txt, me){ | |
txt && displayMessage({ | |
text: Utils.clipboard.text = txt, | |
onclick: /^[a-z]+:./.test(txt) && (() => Utils.openUrlInBrowser(txt)), | |
}, me); | |
} | |
function snapshot(type){ | |
var win = context.focusedWindow; | |
return CmdUtils.getWindowSnapshot(win, {type: type, width: win.innerWidth}); | |
} | |
function imgnow(){ | |
var {document} = CmdUtils; | |
return ( | |
/^image\/./.test(document.contentType) | |
? document.body.firstChild | |
: (CmdUtils.getSelectedNodes(ImgQ)[0] || | |
context.focusedWindow.document.querySelector(ImgQ))); | |
} | |
function src2du(src, ph){ | |
return DUCache[src] || | |
(CmdUtils.getImageSnapshot(src, function(du){ DUCache[src] = du }), | |
DUCache[src] = ph || DUCache['']) | |
} | |
function img2du(img){ | |
var u = DUCache[img.src] | |
if(u) return u | |
var canvas = $('<canvas>', {width: img.width, height: img.height})[0] | |
canvas.getContext('2d').drawImage(img, 0, 0) | |
return DUCache[img.src] = canvas.toDataURL() | |
} | |
function info(){ | |
var doc = CmdUtils.document, {URL: u, title: t} = doc | |
, a = u.startsWith('https://inoreader.com/') && | |
doc.querySelector('.article_current .article_title_link') | |
if(a){ | |
u = a.href | |
t = a.textContent.trim() | |
} | |
return {url: u, title: t} | |
} | |
function parse(txt){ return txt.replace(REA, replr) } | |
function replr(m){ return Aliases[m].text } | |
function wins(){ | |
let w = CmdUtils.window | |
return [w].concat(Array.slice(w)) | |
} | |
function qsa(q){ | |
return Array.concat.apply( | |
0, [for(w of wins()) Array.slice(w.document.querySelectorAll(q))]) | |
} | |
function uni(a, key){ | |
var d = {__proto__: null}; | |
for(let x of a) d[x[key]] = x; | |
return Object.values(d) | |
} | |
function pick(lister, filter){ | |
if(filter){ | |
let re = Utils.regexp(filter, 'i') | |
return [for(x of lister) if(re.test(lister.text(x))) x] | |
} | |
return [...lister] | |
} | |
function ax(href, text){ | |
var a = H(text || href).link(H(href)) | |
return text ? a + '<code class="uri">'+ H(href) +'</code>' : a | |
} | |
function favicon(){ | |
return Utils.currentChromeWindow.gBrowser.selectedTab.image | |
} | |
$.extend(feed, {author: 'satyr', license: 'X'}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment