HackmdEditor.jsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import Penpal from 'penpal';
  4. // Penpal.debug = true;
  5. export default class HackmdEditor extends React.PureComponent {
  6. constructor(props) {
  7. super(props);
  8. this.state = {
  9. };
  10. this.hackmd = null;
  11. this.initHackmdWithPenpal = this.initHackmdWithPenpal.bind(this);
  12. this.notifyBodyChangesHandler = this.notifyBodyChangesHandler.bind(this);
  13. this.saveWithShortcutHandler = this.saveWithShortcutHandler.bind(this);
  14. }
  15. componentDidMount() {
  16. // append iframe with penpal
  17. this.initHackmdWithPenpal();
  18. }
  19. initHackmdWithPenpal() {
  20. const _this = this; // for in methods scope
  21. const url = `${this.props.hackmdUri}/${this.props.pageIdOnHackmd}?both`;
  22. const connection = Penpal.connectToChild({
  23. url,
  24. appendTo: this.refs.iframeContainer,
  25. methods: { // expose methods to HackMD
  26. notifyBodyChanges(document) {
  27. _this.notifyBodyChangesHandler(document);
  28. },
  29. saveWithShortcut(document) {
  30. _this.saveWithShortcutHandler(document);
  31. }
  32. },
  33. });
  34. connection.promise.then(child => {
  35. this.hackmd = child;
  36. if (this.props.initializationMarkdown != null) {
  37. child.setValueOnInit(this.props.initializationMarkdown);
  38. }
  39. });
  40. }
  41. /**
  42. * return markdown document of HackMD
  43. * @return {Promise<string>}
  44. */
  45. getValue() {
  46. return this.hackmd.getValue();
  47. }
  48. setValue(newValue) {
  49. this.hackmd.setValue(newValue);
  50. }
  51. notifyBodyChangesHandler(body) {
  52. // dispatch onChange() when there is difference from 'initializationMarkdown' props
  53. if (this.props.onChange != null && body !== this.props.initializationMarkdown) {
  54. this.props.onChange(body);
  55. }
  56. }
  57. saveWithShortcutHandler(document) {
  58. if (this.props.onSaveWithShortcut != null) {
  59. this.props.onSaveWithShortcut(document);
  60. }
  61. }
  62. render() {
  63. return (
  64. // will be rendered in componentDidMount
  65. <div id='iframe-hackmd-container' ref='iframeContainer'></div>
  66. );
  67. }
  68. }
  69. HackmdEditor.propTypes = {
  70. hackmdUri: PropTypes.string.isRequired,
  71. pageIdOnHackmd: PropTypes.string.isRequired,
  72. initializationMarkdown: PropTypes.string,
  73. onChange: PropTypes.func,
  74. onSaveWithShortcut: PropTypes.func,
  75. };