Просмотр исходного кода

Merge pull request #402 from weseek/feat/Markdown-editor-for-comment-mizobuchi

Feat/markdown editor for comment mizobuchi
Sou Mizobuchi 8 лет назад
Родитель
Сommit
dc57cc5c27

+ 1 - 1
resource/js/app.js

@@ -109,7 +109,7 @@ const componentMappings = {
 };
 // additional definitions if data exists
 if (pageId) {
-  componentMappings['page-comments-list'] = <PageComments pageId={pageId} revisionId={pageRevisionId} revisionCreatedAt={pageRevisionCreatedAt} crowi={crowi} />;
+  componentMappings['page-comments-list'] = <PageComments pageId={pageId} revisionId={pageRevisionId} revisionCreatedAt={pageRevisionCreatedAt} crowi={crowi} crowiRenderer={crowiRenderer} pagePath={pagePath} />;
   componentMappings['page-attachment'] = <PageAttachment pageId={pageId} pageContent={pageContent} crowi={crowi} />;
 }
 if (pagePath) {

+ 1 - 1
resource/js/components/Page.js

@@ -117,7 +117,7 @@ export default class Page extends React.Component {
           isMathJaxEnabled={isMathJaxEnabled}
           renderMathJaxOnInit={true}
       />
-    )
+    );
   }
 }
 

+ 74 - 6
resource/js/components/PageComment/Comment.js

@@ -5,6 +5,7 @@ import dateFnsFormat from 'date-fns/format';
 
 import ReactUtils from '../ReactUtils';
 import UserPicture from '../User/UserPicture';
+import RevisionBody from '../Page/RevisionBody';
 
 /**
  *
@@ -19,11 +20,30 @@ export default class Comment extends React.Component {
   constructor(props) {
     super(props);
 
+    this.state = {
+      html: '',
+    };
+
     this.isCurrentUserIsAuthor = this.isCurrentUserEqualsToAuthor.bind(this);
     this.isCurrentRevision = this.isCurrentRevision.bind(this);
     this.getRootClassName = this.getRootClassName.bind(this);
     this.getRevisionLabelClassName = this.getRevisionLabelClassName.bind(this);
     this.deleteBtnClickedHandler = this.deleteBtnClickedHandler.bind(this);
+    this.renderHtml = this.renderHtml.bind(this);
+  }
+
+  componentWillMount() {
+    this.renderHtml(this.props.comment.comment, this.props.highlightKeywords);
+  }
+
+  componentWillReceiveProps(nextProps) {
+    this.renderHtml(nextProps.comment.comment, nextProps.highlightKeywords);
+  }
+
+  //not used
+  setMarkdown(markdown) {
+    this.setState({ markdown });
+    this.renderHtml(markdown, this.props.highlightKeywords);
   }
 
   isCurrentUserEqualsToAuthor() {
@@ -48,18 +68,63 @@ export default class Comment extends React.Component {
     this.props.deleteBtnClicked(this.props.comment);
   }
 
+  renderRevisionBody() {
+    const config = this.props.crowi.getConfig();
+    const isMathJaxEnabled = !!config.env.MATHJAX;
+    return (
+      <RevisionBody html={this.state.html}
+          inputRef={el => this.revisionBodyElement = el}
+          isMathJaxEnabled={isMathJaxEnabled}
+          renderMathJaxOnInit={true} />
+    );
+  }
+
+  renderHtml(markdown, highlightKeywords) {
+    var context = {
+      markdown,
+      dom: this.revisionBodyElement,
+      currentPagePath: this.props.pagePath,
+    };
+
+    const crowiRenderer = this.props.crowiRenderer;
+    const interceptorManager = this.props.crowi.interceptorManager;
+    interceptorManager.process('preCommentRender', context)
+      .then(() => interceptorManager.process('preCommentPreProcess', context))
+      .then(() => {
+        context.markdown = crowiRenderer.preProcess(context.markdown);
+      })
+      .then(() => interceptorManager.process('postCommentPreProcess', context))
+      .then(() => {
+        var parsedHTML = crowiRenderer.process(context.markdown);
+        context['parsedHTML'] = parsedHTML;
+      })
+      .then(() => interceptorManager.process('preCommentPostProcess', context))
+      .then(() => {
+        context.parsedHTML = crowiRenderer.postProcess(context.parsedHTML, context.dom);
+
+        // highlight
+        if (highlightKeywords != null) {
+          context.parsedHTML = this.getHighlightedBody(context.parsedHTML, highlightKeywords);
+        }
+      })
+      .then(() => interceptorManager.process('postCommentPostProcess', context))
+      .then(() => interceptorManager.process('preCommentRenderHtml', context))
+      .then(() => {
+        this.setState({ html: context.parsedHTML });
+      })
+      // process interceptors for post rendering
+      .then(() => interceptorManager.process('postCommentRenderHtml', context));
+
+  }
+
   render() {
     const comment = this.props.comment;
     const creator = comment.creator;
-
-    // temporary from here
     const isMarkdown = comment.isMarkdown;
-    let markdownText = isMarkdown ? 'markdown' : 'plain';
-    // to here
 
     const rootClassName = this.getRootClassName();
     const commentDate = dateFnsFormat(comment.createdAt, 'YYYY/MM/DD HH:mm');
-    const commentBody = ReactUtils.nl2br(comment.comment);
+    const commentBody = isMarkdown ? this.renderRevisionBody() : ReactUtils.nl2br(comment.comment);
     const creatorsPage = `/user/${creator.username}`;
     const revHref = `?revision=${comment.revision}`;
     const revFirst8Letters = comment.revision.substr(-8);
@@ -73,7 +138,6 @@ export default class Comment extends React.Component {
         <div className="page-comment-main">
           <div className="page-comment-creator">
             <a href={creatorsPage}>{creator.username}</a>
-            <p>{markdownText}!!!</p>
           </div>
           <div className="page-comment-body">{commentBody}</div>
           <div className="page-comment-meta">
@@ -96,4 +160,8 @@ Comment.propTypes = {
   currentRevisionId: PropTypes.string.isRequired,
   currentUserId: PropTypes.string.isRequired,
   deleteBtnClicked: PropTypes.func.isRequired,
+  crowi: PropTypes.object.isRequired,
+  crowiRenderer: PropTypes.object.isRequired,
+  pagePath: PropTypes.string.isRequired,
+  highlightKeywords: PropTypes.string,
 };

+ 7 - 1
resource/js/components/PageComments.js

@@ -123,7 +123,10 @@ export default class PageComments extends React.Component {
         <Comment key={comment._id} comment={comment}
           currentUserId={this.props.crowi.me}
           currentRevisionId={this.props.revisionId}
-          deleteBtnClicked={this.confirmToDeleteComment} />
+          deleteBtnClicked={this.confirmToDeleteComment}
+          crowi={this.props.crowi}
+          crowiRenderer={this.props.crowiRenderer}
+          pagePath={this.props.pagePath} />
       );
     });
   }
@@ -239,4 +242,7 @@ PageComments.propTypes = {
   revisionId: PropTypes.string,
   revisionCreatedAt: PropTypes.number,
   crowi: PropTypes.object.isRequired,
+  crowiRenderer: PropTypes.object.isRequired,
+  pagePath: PropTypes.string.isRequired,
+  highlightKeywords: PropTypes.string,
 };