Skip to content

Instantly share code, notes, and snippets.

@alexkirsz
Created February 9, 2018 18:18
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 alexkirsz/471d7f52f3174172b7a1a96e8eb4362f to your computer and use it in GitHub Desktop.
Save alexkirsz/471d7f52f3174172b7a1a96e8eb4362f to your computer and use it in GitHub Desktop.
Tamper with Facebook's draft editor
// ==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