Created
June 16, 2021 15:50
-
-
Save seleb/de95ae93a6aa9d6e21d721e5e12c31d4 to your computer and use it in GitHub Desktop.
the original guy juicer
This file contains 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
/** | |
* Helper used to replace code in a script tag based on a search regex. | |
* To inject code without erasing original string, using capturing groups; e.g. | |
* ```js | |
* inject(/(some string)/,'injected before $1 injected after'); | |
* ``` | |
* @param searcher Regex to search and replace | |
* @param replacer Replacer string/fn | |
*/ | |
function inject(searcher, replacer) { | |
// find the relevant script tag | |
var scriptTags = document.getElementsByTagName('script'); | |
var scriptTag; | |
var code = ''; | |
for (var i = 0; i < scriptTags.length; ++i) { | |
scriptTag = scriptTags[i]; | |
if (!scriptTag.textContent) | |
continue; | |
var matchesSearch = scriptTag.textContent.search(searcher) !== -1; | |
var isCurrentScript = scriptTag === document.currentScript; | |
if (matchesSearch && !isCurrentScript) { | |
code = scriptTag.textContent; | |
break; | |
} | |
} | |
// error-handling | |
if (!code || !scriptTag) { | |
throw new Error('Couldn\'t find "' + searcher + '" in script tags'); | |
} | |
// modify the content | |
code = code.replace(searcher, replacer); | |
// replace the old script tag with a new one using our modified code | |
var newScriptTag = document.createElement('script'); | |
newScriptTag.textContent = code; | |
scriptTag.insertAdjacentElement('afterend', newScriptTag); | |
scriptTag.remove(); | |
} | |
/** | |
* Helper for getting an array with unique elements | |
* @param {Array} array Original array | |
* @return {Array} Copy of array, excluding duplicates | |
*/ | |
function unique(array) { | |
return array.filter(function (item, idx) { | |
return array.indexOf(item) === idx; | |
}); | |
} | |
// Ex: inject(/(names.sprite.set\( name, id \);)/, '$1console.dir(names)'); | |
/** test */ | |
function kitsyInject(searcher, replacer) { | |
if (!kitsy.queuedInjectScripts.some(function (script) { | |
return searcher.toString() === script.searcher.toString() && replacer === script.replacer; | |
})) { | |
kitsy.queuedInjectScripts.push({ | |
searcher: searcher, | |
replacer: replacer, | |
}); | |
} | |
else { | |
console.warn('Ignored duplicate inject'); | |
} | |
} | |
// Ex: before('load_game', function run() { alert('Loading!'); }); | |
// before('show_text', function run(text) { return text.toUpperCase(); }); | |
// before('show_text', function run(text, done) { done(text.toUpperCase()); }); | |
function before(targetFuncName, beforeFn) { | |
kitsy.queuedBeforeScripts[targetFuncName] = kitsy.queuedBeforeScripts[targetFuncName] || []; | |
kitsy.queuedBeforeScripts[targetFuncName].push(beforeFn); | |
} | |
// Ex: after('load_game', function run() { alert('Loaded!'); }); | |
function after(targetFuncName, afterFn) { | |
kitsy.queuedAfterScripts[targetFuncName] = kitsy.queuedAfterScripts[targetFuncName] || []; | |
kitsy.queuedAfterScripts[targetFuncName].push(afterFn); | |
} | |
function applyInjects() { | |
kitsy.queuedInjectScripts.forEach(function (injectScript) { | |
inject(injectScript.searcher, injectScript.replacer); | |
}); | |
} | |
function applyHooks(root) { | |
var allHooks = unique(Object.keys(kitsy.queuedBeforeScripts).concat(Object.keys(kitsy.queuedAfterScripts))); | |
allHooks.forEach(applyHook.bind(this, root || window)); | |
} | |
function applyHook(root, functionName) { | |
var functionNameSegments = functionName.split('.'); | |
var obj = root; | |
while (functionNameSegments.length > 1) { | |
obj = obj[functionNameSegments.shift()]; | |
} | |
var lastSegment = functionNameSegments[0]; | |
var superFn = obj[lastSegment]; | |
var superFnLength = superFn ? superFn.length : 0; | |
var functions = []; | |
// start with befores | |
functions = functions.concat(kitsy.queuedBeforeScripts[functionName] || []); | |
// then original | |
if (superFn) { | |
functions.push(superFn); | |
} | |
// then afters | |
functions = functions.concat(kitsy.queuedAfterScripts[functionName] || []); | |
// overwrite original with one which will call each in order | |
obj[lastSegment] = function () { | |
var returnVal; | |
var args = [].slice.call(arguments); | |
var i = 0; | |
function runBefore() { | |
// All outta functions? Finish | |
if (i === functions.length) { | |
return returnVal; | |
} | |
// Update args if provided. | |
if (arguments.length > 0) { | |
args = [].slice.call(arguments); | |
} | |
if (functions[i].length > superFnLength) { | |
// Assume funcs that accept more args than the original are | |
// async and accept a callback as an additional argument. | |
return functions[i++].apply(this, args.concat(runBefore.bind(this))); | |
} | |
// run synchronously | |
returnVal = functions[i++].apply(this, args); | |
if (returnVal && returnVal.length) { | |
args = returnVal; | |
} | |
return runBefore.apply(this, args); | |
} | |
return runBefore.apply(this, arguments); | |
}; | |
} | |
/** | |
@file kitsy-script-toolkit | |
@summary Monkey-patching toolkit to make it easier and cleaner to run code before and after functions or to inject new code into script tags | |
@license WTFPL (do WTF you want) | |
@author Original by mildmojo; modified by Sean S. LeBlanc | |
*/ | |
var kitsy = (window.kitsy = window.kitsy || { | |
queuedInjectScripts: [], | |
queuedBeforeScripts: {}, | |
queuedAfterScripts: {}, | |
inject: kitsyInject, | |
before, | |
after, | |
/** | |
* Applies all queued `inject` calls. | |
* | |
* An object that instantiates an class modified via injection will still refer to the original class, | |
* so make sure to reinitialize globals that refer to injected scripts before calling `applyHooks`. | |
*/ | |
applyInjects, | |
/** Apples all queued `before`/`after` calls. */ | |
applyHooks, | |
}); | |
//# sourceMappingURL=index.js.map | |
var once = false; | |
kitsy.before('Editor.prototype.render', function() { | |
if (!once) { | |
console.log('test', this); | |
once = true; | |
const editor = this; | |
const a = editor.stackUnder.drawImage; | |
const b = editor.stackOver.drawImage; | |
const c = editor.stackActive.drawImage; | |
editor.stackUnder.drawImage = (img, x, y) => { | |
editor.stackUnder.save(); | |
editor.stackUnder.scale(Math.sin(Date.now()/60) * .02 + 1.0, Math.cos(Date.now()/70) * .02 + 1.0); | |
editor.stackUnder.rotate(Math.sin(Date.now()/50)*0.05); | |
editor.stackUnder.translate(Math.sin(Date.now()/20) * .5, Math.cos(Date.now()/30) * .5); | |
a.call(editor.stackUnder, img, x, y); | |
editor.stackUnder.restore(); | |
}; | |
editor.stackOver.drawImage = (img, x, y) => { | |
editor.stackOver.save(); | |
editor.stackOver.scale(Math.sin(Date.now()/20) * .02 + 1.0, Math.cos(Date.now()/30) * .02 + 1.0); | |
editor.stackOver.rotate(Math.sin(Date.now()/60)*0.05); | |
editor.stackOver.translate(Math.sin(Date.now()/50) * .5, Math.cos(Date.now()/40) * .5); | |
b.call(editor.stackOver, img, x, y); | |
editor.stackOver.restore(); | |
}; | |
editor.stackActive.drawImage = (img, x, y) => { | |
editor.stackActive.save(); | |
editor.stackActive.scale(Math.sin(Date.now()/50) * .02 + 1.0, Math.cos(Date.now()/40) * .02 + 1.0); | |
editor.stackActive.rotate(Math.sin(Date.now()/20)*0.05); | |
editor.stackActive.translate(Math.sin(Date.now()/60) * .5, Math.cos(Date.now()/70) * .5); | |
c.call(editor.stackActive, img, x, y); | |
editor.stackActive.restore(); | |
}; | |
(function loop() { | |
requestAnimationFrame(loop); | |
editor.render(); | |
}()); | |
} | |
}); | |
kitsy.applyHooks(crewmaker); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment