2
0
Эх сурвалжийг харах

Merge branch 'master' into feat/importer

yusuketk 7 жил өмнө
parent
commit
db5a296f95

+ 3 - 2
config/webpack.common.js

@@ -27,7 +27,8 @@ module.exports = (options) => {
       'js/legacy-presentation':   './resource/js/legacy/crowi-presentation',
       'js/plugin':                './resource/js/plugin',
       'js/ie11-polyfill':         './resource/js/ie11-polyfill',
-      'js/agent-for-hackmd':      './resource/js/agent-for-hackmd',
+      'js/hackmd-agent':          './resource/js/hackmd-agent',
+      'js/hackmd-styles':         './resource/js/hackmd-styles',
       // styles
       'styles/style':                './resource/styles/scss/style.scss',
       'styles/style-presentation':   './resource/styles/scss/style-presentation.scss',
@@ -155,7 +156,7 @@ module.exports = (options) => {
             test: /node_modules/,
             chunks: (chunk) => {
               // ignore patterns
-              return chunk.name != null && !chunk.name.match(/legacy-presentation|ie11-polyfill|agent-for-hackmd/);
+              return chunk.name != null && !chunk.name.match(/legacy-presentation|ie11-polyfill|hackmd-/);
             },
             name: 'js/vendors',
             // minChunks: 2,

+ 34 - 3
lib/routes/hackmd.js

@@ -1,5 +1,6 @@
 const logger = require('@alias/logger')('growi:routes:hackmd');
 const path = require('path');
+const fs = require('graceful-fs');
 const swig = require('swig-templates');
 const axios = require('axios');
 
@@ -10,9 +11,11 @@ module.exports = function(crowi, app) {
 
   // load GROWI agent script for HackMD
   const manifest = require(path.join(crowi.publicDir, 'manifest.json'));
-  const agentScriptPath = path.join(crowi.publicDir, manifest['js/agent-for-hackmd.js']);
+  const agentScriptPath = path.join(crowi.publicDir, manifest['js/hackmd-agent.js']);
+  const stylesScriptPath = path.join(crowi.publicDir, manifest['js/hackmd-styles.js']);
   // generate swig template
   let agentScriptContentTpl = undefined;
+  let stylesScriptContentTpl = undefined;
 
 
   /**
@@ -31,12 +34,10 @@ module.exports = function(crowi, app) {
     }
 
     const origin = `${req.protocol}://${req.get('host')}`;
-    const styleFilePath = origin + manifest['styles/style-hackmd.css'];
 
     // generate definitions to replace
     const definitions = {
       origin,
-      styleFilePath,
     };
     // inject
     const script = agentScriptContentTpl(definitions);
@@ -45,6 +46,35 @@ module.exports = function(crowi, app) {
     res.send(script);
   };
 
+  /**
+   * GET /_hackmd/load-styles
+   *
+   * loadStyles action
+   * This should be access from HackMD and send script to insert styles
+   *
+   * @param {object} req
+   * @param {object} res
+   */
+  const loadStyles = function(req, res) {
+    // generate swig template
+    if (stylesScriptContentTpl == null) {
+      stylesScriptContentTpl = swig.compileFile(stylesScriptPath);
+    }
+
+    const styleFilePath = path.join(crowi.publicDir, manifest['styles/style-hackmd.css']);
+    const styles = fs.readFileSync(styleFilePath).toString().replace(/\s+/g, ' ');
+
+    // generate definitions to replace
+    const definitions = {
+      styles,
+    };
+    // inject
+    const script = stylesScriptContentTpl(definitions);
+
+    res.set('Content-Type', 'application/javascript');
+    res.send(script);
+  };
+
   const validateForApi = async function(req, res, next) {
     // validate process.env.HACKMD_URI
     const hackmdUri = process.env.HACKMD_URI;
@@ -145,6 +175,7 @@ module.exports = function(crowi, app) {
 
   return {
     loadAgent,
+    loadStyles,
     validateForApi,
     integrate,
     saveOnHackmd,

+ 1 - 0
lib/routes/index.js

@@ -220,6 +220,7 @@ module.exports = function(crowi, app) {
   app.get('/trash/*/$'               , loginRequired(crowi, app, false) , page.deletedPageListShowWrapper);
 
   app.get('/_hackmd/load-agent'        , hackmd.loadAgent);
+  app.get('/_hackmd/load-styles'       , hackmd.loadStyles);
   app.post('/_api/hackmd.integrate'    , accessTokenParser , loginRequired(crowi, app) , csrf, hackmd.validateForApi, hackmd.integrate);
   app.post('/_api/hackmd.saveOnHackmd' , accessTokenParser , loginRequired(crowi, app) , csrf, hackmd.validateForApi, hackmd.saveOnHackmd);
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "3.2.0-RC2",
+  "version": "3.2.0-RC3",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",

+ 12 - 3
resource/js/app.js

@@ -155,6 +155,8 @@ Object.keys(componentMappings).forEach((key) => {
  * @param {object} page Page instance
  */
 const saveWithShortcutSuccessHandler = function(page) {
+  const editorMode = crowi.getCrowiForJquery().getCurrentEditorMode();
+
   // show toastr
   toastr.success(undefined, 'Saved successfully', {
     closeButton: true,
@@ -178,12 +180,15 @@ const saveWithShortcutSuccessHandler = function(page) {
   }
   // re-render PageEditor component
   if (componentInstances.pageEditor != null) {
-    componentInstances.pageEditor.setMarkdown(page.revision.body);
+    const updateEditorValue = (editorMode !== 'builtin');
+    componentInstances.pageEditor.setMarkdown(page.revision.body, updateEditorValue);
   }
   // set revision id to PageEditorByHackmd
   if (componentInstances.pageEditorByHackmd != null) {
     componentInstances.pageEditorByHackmd.setRevisionId(pageRevisionId);
-    componentInstances.pageEditorByHackmd.setMarkdown(page.revision.body);
+
+    const updateEditorValue = (editorMode !== 'hackmd');
+    componentInstances.pageEditorByHackmd.setMarkdown(page.revision.body, updateEditorValue);
   }
 };
 
@@ -199,6 +204,11 @@ const errorHandler = function(error) {
 };
 
 const saveWithShortcut = function(markdown) {
+  const editorMode = crowi.getCrowiForJquery().getCurrentEditorMode();
+  if (editorMode == null) {
+    // do nothing
+    return;
+  }
   // get options
   const options = componentInstances.savePageControls.getCurrentOptionsToSave();
 
@@ -226,7 +236,6 @@ const saveWithSubmitButton = function() {
     // do nothing
     return;
   }
-
   // get options
   const options = componentInstances.savePageControls.getCurrentOptionsToSave();
 

+ 6 - 6
resource/js/components/PageEditor.js

@@ -52,7 +52,7 @@ export default class PageEditor extends React.Component {
     this.scrollPreviewByEditorLineWithThrottle = throttle(20, this.scrollPreviewByEditorLine);
     this.scrollPreviewByCursorMovingWithThrottle = throttle(20, this.scrollPreviewByCursorMoving);
     this.scrollEditorByPreviewScrollWithThrottle = throttle(20, this.scrollEditorByPreviewScroll);
-    this.renderWithDebounce = debounce(50, throttle(100, this.renderPreview));
+    this.renderPreviewWithDebounce = debounce(50, throttle(100, this.renderPreview));
     this.saveDraftWithDebounce = debounce(800, this.saveDraft);
   }
 
@@ -65,9 +65,11 @@ export default class PageEditor extends React.Component {
     return this.state.markdown;
   }
 
-  setMarkdown(markdown) {
+  setMarkdown(markdown, updateEditorValue = true) {
     this.setState({ markdown });
-    this.refs.editor.setValue(markdown);
+    if (updateEditorValue) {
+      this.refs.editor.setValue(markdown);
+    }
   }
 
   focusToEditor() {
@@ -104,7 +106,7 @@ export default class PageEditor extends React.Component {
    * @param {string} value
    */
   onMarkdownChanged(value) {
-    this.renderWithDebounce(value);
+    this.renderPreviewWithDebounce(value);
     this.saveDraftWithDebounce();
   }
 
@@ -285,8 +287,6 @@ export default class PageEditor extends React.Component {
       .then(() => interceptorManager.process('preRenderPreviewHtml', context))
       .then(() => {
         this.setState({ html: context.parsedHTML });
-        // set html to the hidden input (for submitting to save)
-        $('#form-body').val(this.state.markdown);
       })
       // process interceptors for post rendering
       .then(() => interceptorManager.process('postRenderPreviewHtml', context));

+ 2 - 2
resource/js/components/PageEditorByHackmd.jsx

@@ -49,9 +49,9 @@ export default class PageEditorByHackmd extends React.PureComponent {
       });
   }
 
-  setMarkdown(markdown) {
+  setMarkdown(markdown, updateEditorValue = true) {
     this.setState({ markdown });
-    if (this.state.isInitialized) {
+    if (this.state.isInitialized && updateEditorValue) {
       this.refs.hackmdEditor.setValue(markdown);
     }
   }

+ 1 - 1
resource/js/components/PageEditorByHackmd/HackmdEditor.jsx

@@ -45,7 +45,7 @@ export default class HackmdEditor extends React.PureComponent {
     connection.promise.then(child => {
       this.hackmd = child;
       if (this.props.initializationMarkdown != null) {
-        this.setValue(this.props.initializationMarkdown);
+        child.setValueOnInit(this.props.initializationMarkdown);
       }
     });
   }

+ 25 - 16
resource/js/agent-for-hackmd.js → resource/js/hackmd-agent.js

@@ -17,19 +17,8 @@ import { debounce } from 'throttle-debounce';
 /* eslint-disable no-console  */
 
 const allowedOrigin = '{{origin}}';         // will be replaced by swig
-const styleFilePath = '{{styleFilePath}}';  // will be replaced by swig
 
 
-/**
- * Insert link tag to load style file
- */
-function insertStyle() {
-  const element = document.createElement('link');
-  element.href = styleFilePath;
-  element.rel = 'stylesheet';
-  document.getElementsByTagName('head')[0].appendChild(element);
-}
-
 /**
  * return the value of CodeMirror
  */
@@ -41,12 +30,31 @@ function getValueOfCodemirror() {
 
 /**
  * set the specified document to CodeMirror
- * @param {string} document
+ * @param {string} value
  */
-function setValueToCodemirror(document) {
+function setValueToCodemirror(value) {
   // get CodeMirror instance
   const editor = window.editor;
-  editor.doc.setValue(document);
+  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;
+  }
+  else {
+    const intervalId = setInterval(() => {
+      if (window.cmClient != null) {
+        clearInterval(intervalId);
+        setValueToCodemirror(newValue);
+      }
+    }, 250);
+  }
 }
 
 /**
@@ -103,6 +111,9 @@ function connectToParentWithPenpal() {
       setValue(newValue) {
         setValueToCodemirror(newValue);
       },
+      setValueOnInit(newValue) {
+        setValueToCodemirrorOnInit(newValue);
+      }
     }
   });
   connection.promise.then(parent => {
@@ -122,8 +133,6 @@ function connectToParentWithPenpal() {
 
   console.log('[HackMD] Loading GROWI agent for HackMD...');
 
-  insertStyle();
-
   window.addEventListener('load', (event) => {
     console.log('loaded');
     addEventListenersToCodemirror();

+ 42 - 0
resource/js/hackmd-styles.js

@@ -0,0 +1,42 @@
+/**
+ * GROWI styles loader for HackMD
+ *
+ * This file will be transpiled as a single JS
+ *  and should be load from HackMD head via 'lib/routes/hackmd.js' route
+ *
+ * USAGE:
+ *  <script src="${hostname of GROWI}/_hackmd/load-styles"></script>
+ *
+ * @author Yuki Takei <yuki@weseek.co.jp>
+ */
+
+/* eslint-disable no-console  */
+
+const styles = '{{styles}}';         // will be replaced by swig
+
+/**
+ * Insert link tag to load style file
+ */
+function insertStyle() {
+  const element = document.createElement('style');
+  element.type = 'text/css';
+  element.appendChild(document.createTextNode(styles));
+  document.getElementsByTagName('head')[0].appendChild(element);
+}
+
+/**
+ * main
+ */
+(function() {
+  // check HackMD is in iframe
+  if (window === window.parent) {
+    console.log('[GROWI] Loading styles for HackMD is not processed because currently not in iframe');
+    return;
+  }
+
+  console.log('[HackMD] Loading GROWI styles for HackMD...');
+
+  insertStyle();
+
+  console.log('[HackMD] GROWI styles for HackMD has successfully loaded.');
+}());