PageEditor.js 2.9 KB

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