Created
February 9, 2018 18:18
-
-
Save alexkirsz/471d7f52f3174172b7a1a96e8eb4362f to your computer and use it in GitHub Desktop.
Tamper with Facebook's draft editor
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
// ==UserScript== | |
// @name Facebook Tamper | |
// @version 0.1 | |
// @author Alexandre Kirszenberg | |
// @match https://www.facebook.com/* | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
function compose(React, ContentState, EditorState, DraftEditor) { | |
const changeState = function(editorState) { | |
// `editorState` represents the editor's state (immutable). | |
// `editorState.getCurrentContent()` represents the editor's content state (immutable). | |
// `ContentState` provides update methods on the current content data structure. | |
// `EditorState` provides update methods on the editor state data structure. | |
// More info on https://draftjs.org/docs/ | |
if (editorState.getCurrentContent().getPlainText() === "hi") { | |
return EditorState.createWithContent(ContentState.createFromText('hello')); | |
} | |
return editorState; | |
}; | |
return class ComposedDraftEditor extends React.Component { | |
constructor() { | |
super(); | |
// We're proxying the DraftEditor component, and as such, we're masking all instance methods of the component. | |
// This proxies those instance methods as well. | |
const proxy = name => this[name] = (...args) => this.ref[name](...args); | |
['focus', 'blur', 'setMode', 'exitCurrentMode', 'restoreEditorDOM', 'setClipboard', 'getClipboard', 'update', 'onDragEnter', 'onDragLeave', 'getEditorKey'].forEach(proxy); | |
} | |
onChildMount(ref) { | |
this.ref = ref; | |
} | |
render() { | |
return React.createElement(DraftEditor, Object.assign({}, this.props, { | |
ref: this.onChildMount.bind(this), | |
// If you want to change text on the fly. | |
onChange: (state) => this.props.onChange(changeState(state)), | |
// An attempt at changing text on submit, but the new state returned isn't being used. | |
// There's probably a better way to do this. One way would be to call `this.props.onChange`, wait | |
// for a state update, then call `this.props.handleReturn`. | |
// handleReturn: (event, state) => this.props.handleReturn(event, changeState(state)), | |
})); | |
} | |
}; | |
} | |
// Hooks into Facebook's define method, allowing for replacing modules on the fly. | |
const customDefine = define => (name, deps, factory, ...args) => { | |
if (name === 'DraftEditor.react') { | |
// __d expects the factory function to have a length of 9 | |
const newFactory = function (a1, req, a3, a4, mod, a6, a7, a8, a9) { | |
factory(a1, req, a3, a4, mod, a6, a7, a8, a9); | |
mod.exports = compose(require('React'), require('ContentState'), require('EditorState'), mod.exports); | |
}; | |
return define(name, deps, newFactory); | |
} | |
return define(name, deps, factory, ...args); | |
}; | |
let define; | |
Object.defineProperty(window, '__d', { | |
get() { | |
return define; | |
}, | |
set(newValue) { | |
define = customDefine(newValue); | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment