Skip to content

Instantly share code, notes, and snippets.

@qntnt
Created October 28, 2015 06:57
Show Gist options
  • Save qntnt/c408dbe7738993a90a74 to your computer and use it in GitHub Desktop.
Save qntnt/c408dbe7738993a90a74 to your computer and use it in GitHub Desktop.
In-Place Markdown EditArea (React)
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true,
tables: true,
breaks: true,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: true
});
class EditArea extends React.Component {
constructor() {
super();
let text = `# Click Me to Edit!
Then click outside of this card.
# Table
Languages | Variations
:------------: | :--------:
**Python** | ---
**Haskell** | ---
**Javascript** | ES6, ES5
**C** | ---
**Scheme** | ---
# Python
\`\`\`python
def foo(bar):
return bar + 1
\`\`\`
# Haskell
\`\`\`
foo bar = bar + 1
\`\`\`
# Javascript
**ES6**
\`\`\`
function foo(bar) {
return bar + 1;
}
\`\`\`
**ES5**
\`\`\`
var foo = function(bar) {
return bar + 1;
};
\`\`\`
# C
\`\`\`
function foo(int bar) {
return bar + 1;
}
\`\`\`
# Scheme
\`\`\`
(define (foo bar) (+ bar 1))
\`\`\``;
this.state = {
editing: false,
content: text,
renderedContent: marked(text)
};
}
renderContent = () => {
console.info("Rendering...");
this.setState({
renderedContent: marked(this.state.content)
});
}
getText() {
let text = this.refs.editArea.getDOMNode().innerHTML;
console.log("text: ", text)
return text;
}
handleFocus = () => {
console.info('Toggling edit... ', !this.state.editing);
this.setState({
editing: true
});
}
format(str) {
console.log('Before format: ',str);
for (let i=0; i<str.length; i++){
if (str.substring(i, i+5) === "<div>") {
str = str.slice(0, i)+"\n"+str.slice(i+5, str.length);
i = i - 5;
}
if (str.substring(i, i+6) === "</div>") {
str = str.slice(0, i)+str.slice(i+6, str.length);
i = i - 6;
}
if (str.substring(i, i+4) === "<br>") {
str = str.slice(0, i)+"\n"+str.slice(i+4, str.length);
i = i - 4;
}
}
console.log('After format: ',str);
return str;
}
handleBlur = () => {
let text = this.format(this.getText());
this.setState({
editing: false,
content: text,
renderedContent: marked(text)
});
}
render() {
if (this.state.editing) {
return (
<pre contentEditable="true" ref="editArea" onFocus={this.handleFocus} onBlur={this.handleBlur}>{this.state.content}</pre>
);
} else {
return (
<div contentEditable="true" onFocus={this.handleFocus} onBlur={this.handleBlur} dangerouslySetInnerHTML={{__html: this.state.renderedContent}}></div>
);
}
}
}
class Card extends React.Component {
render() {
return <div className="ui centered card"><div className="content"><EditArea/></div></div>;
}
}
class App extends React.Component {
render() {
return <div className="ui basic segment"><Card/></div>;
}
}
React.render( <App /> , document.getElementById('app'));
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.4/semantic.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js"></script>
table, th, tr, td
border: 1px solid black
td
padding: 5px 10px 5px 10px
th
background-color: lightgray
<link href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.4/semantic.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment