PageEditor.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import Editor from './PageEditor/Editor';
  4. import Preview from './PageEditor/Preview';
  5. export default class PageEditor extends React.Component {
  6. constructor(props) {
  7. super(props);
  8. this.state = {
  9. markdown: this.props.markdown,
  10. };
  11. // initial preview
  12. this.renderPreview();
  13. this.initCaretPosition = this.initCaretPosition.bind(this);
  14. this.onMarkdownChanged = this.onMarkdownChanged.bind(this);
  15. }
  16. /**
  17. * initialize caret position of editor
  18. * @param {string} value
  19. */
  20. initCaretPosition(position) {
  21. console.log(this.refs.editor);
  22. this.refs.editor.initCaretPosition(position);
  23. }
  24. /**
  25. * the change event handler for `markdown` state
  26. * @param {string} value
  27. */
  28. onMarkdownChanged(value) {
  29. this.setState({
  30. markdown: value,
  31. html: '',
  32. });
  33. this.renderPreview();
  34. }
  35. renderPreview() {
  36. const config = this.props.crowi.config;
  37. // generate options obj
  38. const rendererOptions = {
  39. // see: https://www.npmjs.com/package/marked
  40. marked: {
  41. breaks: config.isEnabledLineBreaks,
  42. }
  43. };
  44. // render html
  45. var context = {
  46. markdown: this.state.markdown,
  47. dom: this.previewElement,
  48. currentPagePath: decodeURIComponent(location.pathname)
  49. };
  50. this.props.crowi.interceptorManager.process('preRenderPreview', context)
  51. .then(() => crowi.interceptorManager.process('prePreProcess', context))
  52. .then(() => {
  53. context.markdown = crowiRenderer.preProcess(context.markdown, context.dom);
  54. })
  55. .then(() => crowi.interceptorManager.process('postPreProcess', context))
  56. .then(() => {
  57. var parsedHTML = crowiRenderer.render(context.markdown, context.dom, rendererOptions);
  58. context['parsedHTML'] = parsedHTML;
  59. })
  60. .then(() => crowi.interceptorManager.process('postRenderPreview', context))
  61. .then(() => crowi.interceptorManager.process('preRenderPreviewHtml', context))
  62. .then(() => {
  63. this.setState({html: context.parsedHTML});
  64. // set html to the hidden input (for submitting to save)
  65. $('#form-body').val(this.state.markdown);
  66. })
  67. // process interceptors for post rendering
  68. .then(() => crowi.interceptorManager.process('postRenderPreviewHtml', context));
  69. }
  70. render() {
  71. return (
  72. <div className="row">
  73. <div className="col-md-6 col-sm-12 page-editor-editor-container">
  74. <Editor ref="editor" value={this.state.markdown} onChange={this.onMarkdownChanged} />
  75. </div>
  76. <div className="col-md-6 hidden-sm hidden-xs page-editor-preview-container">
  77. <Preview html={this.state.html} inputRef={el => this.previewElement = el} />
  78. </div>
  79. </div>
  80. )
  81. }
  82. }
  83. PageEditor.propTypes = {
  84. crowi: PropTypes.object.isRequired,
  85. markdown: PropTypes.string,
  86. };