/** * GROWI agent for HackMD * * This file will be transpiled as a single JS * and should be load from HackMD head via 'routes/hackmd.js' route * * USAGE: * * * @author Yuki Takei */ import connectToParent from 'penpal/lib/connectToParent'; import { debounce } from 'throttle-debounce'; const DEBUG_PENPAL = false; /* eslint-disable no-console */ const allowedOrigin = '<%= origin %>'; // will be replaced by ejs /** * return the value of CodeMirror */ function getValueOfCodemirror() { // get CodeMirror instance const editor = window.editor; return editor.doc.getValue(); } /** * set the specified document to CodeMirror * @param {string} value */ function setValueToCodemirror(value) { // get CodeMirror instance const editor = window.editor; editor.doc.setValue(value); } /** * set the specified document to CodeMirror on window loaded * @param {string} value */ function setValueToCodemirrorOnInit(newValue) { if (window.cmClient != null) { setValueToCodemirror(newValue); return; } const intervalId = setInterval(() => { if (window.cmClient != null) { clearInterval(intervalId); setValueToCodemirror(newValue); } }, 250); } /** * postMessage to GROWI to notify body changes * @param {string} body */ function postParentToNotifyBodyChanges(body) { window.growi.notifyBodyChanges(body); } // generate debounced function const debouncedPostParentToNotifyBodyChanges = debounce(800, postParentToNotifyBodyChanges); /** * postMessage to GROWI to save with shortcut * @param {string} document */ function postParentToSaveWithShortcut(document) { window.growi.saveWithShortcut(document); } function addEventListenersToCodemirror() { // get CodeMirror instance const codemirror = window.CodeMirror; // get CodeMirror editor instance const editor = window.editor; // e.g. 404 not found if (codemirror == null || editor == null) { return; } // == change event editor.on('change', (cm, change) => { if (change.origin === 'ignoreHistory') { // do nothing because this operation triggered by other user return; } debouncedPostParentToNotifyBodyChanges(cm.doc.getValue()); }); // == save event // Reset save commands and Cmd-S/Ctrl-S shortcuts that initialized by HackMD codemirror.commands.save = function(cm) { postParentToSaveWithShortcut(cm.doc.getValue()); }; delete editor.options.extraKeys['Cmd-S']; delete editor.options.extraKeys['Ctrl-S']; } function connectToParentWithPenpal() { const connection = connectToParent({ parentOrigin: allowedOrigin, // Methods child is exposing to parent methods: { getValue() { return getValueOfCodemirror(); }, setValue(newValue) { setValueToCodemirror(newValue); }, setValueOnInit(newValue) { setValueToCodemirrorOnInit(newValue); }, }, debug: DEBUG_PENPAL, }); connection.promise .then((parent) => { window.growi = parent; }) .catch((err) => { console.log(err); }); } /** * main */ (function() { // check HackMD is in iframe if (window === window.parent) { console.log('[GROWI] Loading agent for HackMD is not processed because currently not in iframe'); return; } console.log('[HackMD] Loading GROWI agent for HackMD...'); window.addEventListener('load', () => { addEventListenersToCodemirror(); }); connectToParentWithPenpal(); console.log('[HackMD] GROWI agent for HackMD has successfully loaded.'); }());