Skip to content

Instantly share code, notes, and snippets.

@DarrenSem
Last active January 16, 2023 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DarrenSem/b5be4d9ad5e0fd0219cd1165a6a757b2 to your computer and use it in GitHub Desktop.
Save DarrenSem/b5be4d9ad5e0fd0219cd1165a6a757b2 to your computer and use it in GitHub Desktop.
REPL.js AKA eval.js -- Bookmarklet to append to current webpage a text input field + global-scope [EVAL] button - ALSO evaluates console.[log|error|warn|info|assert]
// REPL.js AKA eval.js -- REPL.js AKA eval.js -- Bookmarklet to append to current webpage a text input field + global-scope [EVAL] button - ALSO evaluates console.[log|error|warn|info|assert]
// javascript:void function(){var a=document,b=(b,c)=>Object.assign(a.createElement(b||"button"),c),c=b("pre"),d=b("div",{contentEditable:!0}),e="innerText",f=b(0,{[e]:"EVAL",onclick:(a,b,c,f=new Date().toLocaleTimeString(),g=location,h,i=/\bconsole\s*\.(log|error|warn|info|assert)\s*\(([^)])/g)=>{try{a=d[e],b=(g._=[],(i.test(a)?"let _=location,_log=(...a)=>{_._.push(a.join(\" \"));"+"\nlet m=(String(a[0]).match(/^<([aefgilnorw_ts]{3,6})>$/)||[])[1]||\"log\";console[m](...(a.slice(m==\"assert\"?1:0)))"+"\n};\n":"")+a).replace(i,`_log('<$1>', $2`),c=(0,eval)(b)+"",g._&&(c=g._.concat([c]).join("\n"))}catch(a){c=a.stack||a.message,c+="\n"+b}d[e]+=/[\n\r]/.test(c)?`\n\n/\* ${f}:\n${c.replace(/\*\//g,"* /")}\n*\/`:`\n// ${f}: ${c}`,d.focus()}});[f,c].forEach(({style:a},b)=>{a.border=b?"solid":"ridge",a.background=b?"#0aa":"#0a0",a.padding="1px 3px",a.margin=b?"9px 3px 0px 3px":"1px 3px"}),a.body.append(c,f,b(0,{[e]:"reset",onclick:()=>(d[e]="",d).focus()})),c.appendChild(d).focus()}()
var doc = document;
var create = (type, optionalProps) => Object.assign( doc.createElement(type || "button"), optionalProps );
var wrapper = create("pre");
var editable = create("div", {
contentEditable: true
});
var propEditable = "innerText";
var button = create(0, {
[propEditable]: "EVAL",
onclick: (
_text,
_code,
_result,
_now = (new Date).toLocaleTimeString(),
_ = location,
_undefined
, CONSOLE_REGEXP = "_LOG?" === "_LOG?" ? /\bconsole\s*\.(log|error|warn|info|assert)\s*\(([^)])/g : ""
) => {
try {
_text = editable[propEditable];
_code = (
// remove (or disable) all "_LOG" lines to reduce minified size (e.g. for mobile bookmarklet)
"_LOG?" === "_LOG?"
? (
_._=[], ( (
CONSOLE_REGEXP.test(_text) ? (
'let _=location,_log=(...a)=>{_._.push(a.join(" "));'
+ ( "_NATIVE_CONSOLE_TOO?" === "_NATIVE_CONSOLE_TOO?" ? '\nlet m=(String(a[0]).match(/^<([aefgilnorw_ts]{3,6})>$/)||[])[1]||"log";console[m](...(a.slice(m=="assert"?1:0)))' : "")
+ '\n};\n'
) : ""
) + _text )
) :
_text
)
.replace(CONSOLE_REGEXP, "_LOG?" === "_LOG?" ? `_log('<$1>', $2` : "")
;
_result = String( (0, eval)(_code) ); // Bookmarklet FAIL if eval(_code) instead of (0, eval)(_code)
if(_._) _result = _._.concat( [ _result ] ).join("\n");
} catch(e) {
_result = e.stack || e.message;
if("_LOG?" === "_LOG?") _result += "\n" + _code;
};
editable[propEditable] += (
/[\n\r]/.test(_result)
? `\n\n/\* ${ _now }:\n${ _result.replace( /\*\//g, "* /" ) }\n*\/`
: `\n// ${ _now }: ${ _result }`
);
editable.focus();
}
});
[button, wrapper].forEach( ( {style}, i ) => {
style.border = i ? "solid" : "ridge"; // "solid" is less subtle than "ridge", but tbh it was a toss-up
style.background = i ? "#0aa" : "#0a0";
style.padding = "1px 3px";
style.margin = i ? "9px 3px 0px 3px" : "1px 3px";
});
doc.body.append(
wrapper,
button,
create(0, {
[propEditable]: "reset",
onclick: event => ( editable[propEditable] = "", editable ).focus()
})
);
wrapper.appendChild(editable).focus();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment