Skip to content

Instantly share code, notes, and snippets.

@cllu
Created March 11, 2016 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cllu/77e19f5cd08945fbf2fd to your computer and use it in GitHub Desktop.
Save cllu/77e19f5cd08945fbf2fd to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Draft • Decorators</title>
<link rel="stylesheet" href="../../dist/Draft.css" />
</head>
<body>
<div id="target"></div>
<script src="../../node_modules/react/dist/react.js"></script>
<script src="../../node_modules/react-dom/dist/react-dom.js"></script>
<script src="../../node_modules/immutable/dist/immutable.js"></script>
<script src="../../node_modules/babel-core/browser.js"></script>
<script src="../../dist/Draft.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.js"></script>
<script type="text/babel">
'use strict';
const {CompositeDecorator, Editor, EditorState} = Draft;
class MarkdownEditorExample extends React.Component {
constructor() {
super();
const compositeDecorator = new CompositeDecorator([
{
strategy: h2Strategy,
component: H2Span,
},
{
strategy: h1Strategy,
component: H1Span,
},
{
strategy: boldStrategy,
component: BoldSpan,
},
]);
this.state = {
editorState: EditorState.createEmpty(compositeDecorator),
};
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => {
this.setState({editorState, marked: editorState.getCurrentContent().getPlainText()});
}
this.logState = () => console.log(this.state.editorState.toJS());
}
render() {
return (
<div style={styles.root}>
<div style={styles.editor} onClick={this.focus}>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
placeholder="Write a tweet..."
ref="editor"
spellCheck={true}
/>
</div>
<input
onClick={this.logState}
style={styles.button}
type="button"
value="Log State"
/>
<div dangerouslySetInnerHTML={{__html: marked(this.state.marked||'')}}/>
</div>
);
}
}
/**
* Super simple decorators for handles and hashtags, for demonstration
* purposes only. Don't reuse these regexes.
*/
const H1_REGEX = /# [\w]+/g;
const H2_REGEX = /## [\w]+/g;
const BOLD_REGEX = /\*\*[\w]+\*\*/g;
function h1Strategy(contentBlock, callback) {
findWithRegex(H1_REGEX, contentBlock, callback);
}
function h2Strategy(contentBlock, callback) {
findWithRegex(H2_REGEX, contentBlock, callback);
}
function boldStrategy(contentBlock, callback) {
findWithRegex(BOLD_REGEX, contentBlock, callback);
}
function findWithRegex(regex, contentBlock, callback) {
const text = contentBlock.getText();
let matchArr, start;
while ((matchArr = regex.exec(text)) !== null) {
start = matchArr.index;
callback(start, start + matchArr[0].length);
}
}
const H1Span = (props) => {
return <h1 {...props} style={styles.h1}>{props.children}</h1>;
};
const H2Span = (props) => {
return <h2 {...props} style={styles.h2}>{props.children}</h2>;
};
const BoldSpan = (props) => {
return <span {...props} style={styles.bold}>{props.children}</span>;
};
const styles = {
root: {
fontFamily: '\'Helvetica\', sans-serif',
padding: 20,
width: 600,
},
h1: {
fontSize: 30
},
h2: {
fontSize: 26
},
bold: {
fontWeight: 'bold'
},
editor: {
border: '1px solid #ddd',
cursor: 'text',
fontSize: 16,
minHeight: 40,
padding: 10,
},
button: {
marginTop: 10,
textAlign: 'center',
},
handle: {
color: 'rgba(98, 177, 254, 1.0)',
direction: 'ltr',
unicodeBidi: 'bidi-override',
},
hashtag: {
color: 'rgba(95, 184, 138, 1.0)',
},
};
ReactDOM.render(
<MarkdownEditorExample />,
document.getElementById('target')
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment