UNPKG

safari-ctl

Version:

A Command Line Tool to control Safari for MacOS. (Browsing/FillingForm/GetSetCopyURL/JavascriptInjection/GetTitle/Search)

270 lines (258 loc) 9.65 kB
#!/usr/bin/env node // Generated by CoffeeScript 2.4.1 //!/usr/bin/env coffee var AppName, D, E, GetOpt, OsaScript, P, PackageName, checkError, ctx, doActivateIfNecessary, e, optUsages; GetOpt = require('@kssfilo/getopt'); OsaScript = require('node-osascript'); AppName = "safari-ctl"; PackageName = "safari-ctl"; P = console.log; E = (e) => { var ref, ref1; switch (false) { case (ref = typeof e) !== 'string' && ref !== 'value': return console.error(e); case !ctx.isDebugMode: return console.error(e); default: if ((ref1 = e[0]) != null ? ref1.message : void 0) { return console.error(e[0].message); } else { return console.error(e.toString()); } } }; D = (str) => { if (ctx.isDebugMode) { return E(`${AppName}:` + str); } }; ctx = { command: 'print', isDebugMode: false, isRecipeJsDebugMode: false, url: null, doActivate: false, javaScript: null, query: null, text: null, dropResult: false }; optUsages = { h: "show this help", d: "debug mode", p: "print current Safari's URL(default)", t: "print current Safari's title", g: "print selected string on current Safari's tab", c: "copy current Safari's URL into the clipboard", s: ["URL", "set <URL> to Safari's active tab"], S: ["URL", "same as -s but set focus to Safari"], q: ["query", "search <query> to Safari's active tab"], Q: ["URL", "same as -q but set focus to Safari"], m: "marks all <a> link with number to click by next -a command(*)", a: ["number", "click <number> link. you can know link number by -m command(*)"], M: "marks all <input> with number to click/set by next -A command(*)", A: ["number", "click <number> input. you can know input number by -M command(*)"], I: ["string", "works with -A, Input <string> instead of click. for filling form(*)"], b: "history back(*)", f: "history forward(*)", n: "scroll to next page(*)", N: "scroll to previous page (*)", j: ["javascript", "run <javascript> on active tab(*)"], J: ["javascript", "same as s but set focus to Safari(*)"] }; try { GetOpt.setopt('h?dptgcs:S:q:Q:ma:MA:I:bfnNj:J:'); } catch (error) { e = error; switch (e.type) { case 'unknown': E(`Unknown option:${e.opt}`); break; case 'required': E(`Required parameter for option:${e.opt}`); } process.exit(1); } try { GetOpt.getopt(function(o, p) { var index; switch (o) { case 'h': case '?': ctx.command = 'usage'; if (p[0] !== '') { return ctx.restCommand = p[0]; } break; case 'd': return ctx.isDebugMode = true; case 'c': return ctx.command = 'copy'; case 'p': return ctx.command = 'print'; case 's': ctx.command = 'set'; return ctx.url = p[0]; case 'S': ctx.command = 'set'; ctx.url = p[0]; return ctx.doActivate = true; case 't': return ctx.command = 'printTitle'; case 'j': ctx.command = 'javaScript'; return ctx.javaScript = p[0]; case 'J': ctx.command = 'javaScript'; ctx.javaScript = p[0]; return ctx.doActivate = true; case 'g': ctx.command = 'javaScript'; return ctx.javaScript = "document.getSelection().toString()"; case 'q': ctx.command = 'search'; return ctx.query = p[0]; case 'Q': ctx.command = 'search'; ctx.query = p[0]; return ctx.doActivate = true; case 'm': ctx.command = 'javaScript'; return ctx.javaScript = 'var $OSA$=document.getElementsByTagName("a");for(var i=0;i<$OSA$.length;i++){v=$OSA$[i];v.innerHTML="<span style=background-color:yellow>"+i+"</span>:"+v.innerHTML;}'; case 'M': ctx.command = 'javaScript'; return ctx.javaScript = 'var $OSA$=document.getElementsByTagName("input");for(var i=0;i<$OSA$.length;i++){v=$OSA$[i];var e=document.createElement("span");e.style="background-color:lightgreen";e.innerText=i;v.before(e);}'; case 'a': ctx.command = 'javaScript'; index = Number(p[0]); ctx.javaScript = `var $OSA$=document.getElementsByTagName('a');$OSA$[${index}].click()`; return ctx.dropResult = true; case 'A': ctx.command = 'javaScript'; index = Number(p[0]); ctx.javaScript = `var $OSA$=document.getElementsByTagName('input');$OSA$[${index}].click()`; return ctx.dropResult = true; case 'I': ctx.text = p[0]; return ctx.dropResult = true; case 'b': ctx.command = 'javaScript'; return ctx.javaScript = "history.back()"; case 'f': ctx.command = 'javaScript'; return ctx.javaScript = "history.forward()"; case 'n': ctx.command = 'javaScript'; ctx.javaScript = "window.scrollBy({top:window.innerHeight,left:0,behavior:'smooth'})"; return ctx.dropResult = true; case 'N': ctx.command = 'javaScript'; ctx.javaScript = "window.scrollBy({top:-window.innerHeight,left:0,behavior:'smooth'})"; return ctx.dropResult = true; } }); if (ctx.command === 'usage') { P(`## Command line\n\n ${AppName} [options]\n \n A Command Line Tool to control Safari for MacOS. (Browsing/FillingForm/GetSetCopyURL/JavascriptInjection/GetTitle/Search)\n \n Copyright (C) 2019-2019 @kssfilo(https://kanasys.com/gtech/)\n\n## Prepare\n\n(*)You must enable the 'Allow JavaScript from Apple Events' option in Safari's Develop menu to use some features.\n\n## Options\n\n${GetOpt.getHelp(optUsages)} \n\n## Examples\n\n### Get current URL on Safari\n\n $ ${AppName}\n https://github.com\n\n### Copy current URL on Safari to the clipboard\n\n $ ${AppName} -s\n\n### Open specified URL on Safari\n\n $ ${AppName} -s 'http://github.com'\n # withoug focus\n\n $ ${AppName} -S 'github.com'\n # with focus(omiting scheme->appends https://)\n\n### Gets window title\n\n $ ${AppName} -t\n\n### Navigating by command line\n\n $ ${AppName} -m\n # marks all <a> with numbers\n\n $ ${AppName} -a 32\n # click 32'th <a>\n\n $ ${AppName} -b\n # history back\n\n $ ${AppName} -M\n # marks all <input> with numbers\n\n $ ${AppName} -A 0 -I 'Japan'\n # Fill 0th input with 'Japan'\n\n $ ${AppName} -A 1\n # click 1st input button\n\n### Searchs Bing with word "Japan" (JavaScript injection)\n\n $ ${AppName} -s 'https://bing.com'\n $ ${AppName} -j 'document.getElementById("sb_form_q").value="Japan";document.getElementById("sb_form_go").click()'\n\n### Print string in Bing search form\n\n $ ${AppName} -j 'document.getElementById("sb_form_q").value'\n Japan`); process.exit(0); } D(`==starting ${AppName}`); if (ctx.javaScript) { ctx.javaScript = ctx.javaScript.replace(/"/g, '\\"'); } if (ctx.url && !ctx.url.match(/^https?:\/\//)) { ctx.url = "https://" + ctx.url; } D("sanity checking.."); if (ctx.text && !ctx.javaScript) { throw "-I works with -A"; } if (ctx.text && ctx.javaScript) { D("CHECK"); ctx.javaScript = ctx.javaScript.replace(/click\(\)$/, `value='${ctx.text}'`); } D("..OK"); D("-------"); D("-options"); D(`${JSON.stringify(ctx, null, 2)}`); if (ctx.isCheckCommand || ctx.isDebugMode) { if (ctx.restCommand != null) { E(`command:${ctx.restCommand}`); } if (ctx.restCommand != null) { E(`method:${ctx.command}`); } if (ctx.restParam != null) { E(`params:${JSON.stringify(ctx.restParam)}`); } } checkError = (e) => { if (e) { P(e.toString()); return process.exit(1); } }; doActivateIfNecessary = (cb) => { if (ctx.doActivate) { return OsaScript.execute("tell application \"safari\"\nactivate\nend tell", cb); } else { return cb(null, null, null); } }; switch (ctx.command) { case 'print': OsaScript.execute("tell application \"safari\"\nURL in front document\nend tell", (e, r, w) => { checkError(e); return P(r); }); break; case 'printTitle': OsaScript.execute("tell application \"safari\"\nname of front document\nend tell", (e, r, w) => { checkError(e); return P(r); }); break; case 'copy': OsaScript.execute("tell application \"safari\"\nset curURL to URL in front document\nset the clipboard to curURL\nend tell", (e, r, w) => { return checkError(e); }); break; case 'set': OsaScript.execute("tell application \"safari\"\nset URL in front document to URLTOSET\nend tell", { URLTOSET: ctx.url }, (e, r, w) => { checkError(e); return doActivateIfNecessary((e, r, w) => { return checkError(e); }); }); break; case 'search': OsaScript.execute("tell application \"safari\"\nsearch the web in front document for QUERY\nend tell", { QUERY: ctx.query }, (e, r, w) => { checkError(e); return doActivateIfNecessary((e, r, w) => { return checkError(e); }); }); break; case 'javaScript': D(ctx.javaScript); doActivateIfNecessary((e, r, w) => { checkError(e); return OsaScript.execute("tell application \"safari\"\ndo JavaScript TORUN in front document\nend tell", { TORUN: ctx.javaScript }, (e, r, w) => { checkError(e); if (r && !ctx.dropResult) { return P(r); } }); }); } } catch (error) { e = error; E(console.error(e.toString())); process.exit(1); }