Procházet zdrojové kódy

Merge pull request #461 from weseek/master

release v3.1.4
Yuki Takei před 7 roky
rodič
revize
4643ff7d32

+ 13 - 4
CHANGES.md

@@ -1,14 +1,25 @@
 CHANGES
 ========
 
-## 3.1.3-RC
+## 3.1.4-RC
+
+* Feature: Support [blockdiag](http://blockdiag.com)
+* Feature: Add `BLOCKDIAG_URI` environment variable
+* Fix: sanitize `#raw-text-original` content with 'entities'
+* Fix: page.rename api doesn't work
+* Support: Upgrade libs
+    * markdown-it-toc-and-anchor-with-slugid
+
+
+## 3.1.3
 
 * Feature: Write comment with Markdown
 * Improvement: Support some placeholders for template page
 * Improvement: Omit unnecessary response header
 * Improvement: Support LDAP attribute mappings for user's full name
 * Fix: HTML escaped characters in markdown are unescaped unexpectedly after page is saved
-
+* Fix: Posting to Slack doesn't work
+    * Introduced by 3.1.0
 
 ## 3.1.2
 
@@ -28,8 +39,6 @@ CHANGES
         :::
         ~~~
 * Improvement: Escape iframe tag in block codes
-* Fix: Posting to Slack doesn't work
-    * Introduced by 3.1.0
 * Support: Upgrade libs
     * assets-webpack-plugin
     * googleapis

+ 3 - 1
README.md

@@ -159,10 +159,12 @@ Environment Variables
     * NODE_ENV: `production` OR `development`.
     * PORT: Server port. default: `3000`
     * REDIS_URL: URI to connect to Redis (to session store).
-    * SESSION_NAME: The name of the session ID cookie to set in the response by Express. default: `connect.sid`
     * ELASTICSEARCH_URI: URI to connect to Elasticearch.
+    * PLANTUML_URI: URI to connect to [PlantUML](http://plantuml.com/) server.
+    * BLOCKDIAG_URI: URI to connect to [blockdiag](http://http://blockdiag.com/) server.
     * PASSWORD_SEED: A password seed used by password hash generator.
     * SECRET_TOKEN: A secret key for verifying the integrity of signed cookies.
+    * SESSION_NAME: The name of the session ID cookie to set in the response by Express. default: `connect.sid`
     * FILE_UPLOAD: `aws` (default), `local`, `none`
 
 

+ 1 - 0
lib/models/config.js

@@ -465,6 +465,7 @@ module.exports = function(crowi) {
       isSavedStatesOfTabChanges: Config.isSavedStatesOfTabChanges(config),
       env: {
         PLANTUML_URI: env.PLANTUML_URI || null,
+        BLOCKDIAG_URI: env.BLOCKDIAG_URI || null,
         MATHJAX: env.MATHJAX || null,
       },
     };

+ 8 - 5
lib/routes/page.js

@@ -1106,9 +1106,10 @@ module.exports = function(crowi, app) {
 
     Page.findPageByPath(newPagePath)
     .then(function(page) {
-      // if page found, cannot cannot rename to that path
-      return res.json(ApiResponse.error(`このページ名は作成できません (${newPagePath})。ページが存在します。`));
-    }).catch(function(err) {
+      if (page != null) {
+        // if page found, cannot cannot rename to that path
+        return res.json(ApiResponse.error(`このページ名は作成できません (${newPagePath})。ページが存在します。`));
+      }
 
       Page.findPageById(pageId)
       .then(function(pageData) {
@@ -1124,12 +1125,14 @@ module.exports = function(crowi, app) {
           return Page.rename(pageData, newPagePath, req.user, options);
         }
 
-      }).then(function() {
+      })
+      .then(function() {
         var result = {};
         result.page = page;
 
         return res.json(ApiResponse.success(result));
-      }).catch(function(err) {
+      })
+      .catch(function(err) {
         return res.json(ApiResponse.error('Failed to update page.'));
       });
     });

+ 7 - 2
lib/util/middlewares.js

@@ -1,5 +1,6 @@
-var debug = require('debug')('growi:lib:middlewares');
-var md5 = require('md5');
+const debug = require('debug')('growi:lib:middlewares');
+const md5 = require('md5');
+const entities = require('entities');
 
 exports.csrfKeyGenerator = function(crowi, app) {
   return function(req, res, next) {
@@ -178,6 +179,10 @@ exports.swigFilters = function(app, swig) {
       }
     });
 
+    swig.setFilter('sanitize', function(string) {
+      return entities.encodeHTML(string);
+    });
+
     next();
   };
 };

+ 0 - 36
lib/views/layout-growi/base/layout.html

@@ -26,42 +26,6 @@
 
 </div><!-- /.container-fluid -->
 
-
-<!-- Side Scroll Bar-->
-<script>
-  /*
-   * Disabled temporally -- 2018.06.06 Yuki Takei
-   * see https://weseek.myjetbrains.com/youtrack/issue/GC-278
-   *
-  function DrawScrollbar() {
-    var h = window.innerHeight - document.getElementById('page-header').clientHeight ;
-    $('#revision-toc-content').slimScroll({
-      railVisible: true,
-      position: 'right',
-      height: h,
-    });
-  }
-
-  $(function(){
-    DrawScrollbar();
-  });
-
-  (function () {
-    var timer = 0;
-
-    window.onresize = function () {
-      if (timer > 0) {
-        clearTimeout(timer);
-      }
-
-      timer = setTimeout(function () {
-        DrawScrollbar();
-      }, 200);
-    };
-  }());
-  */
-  </script>
-
 <footer class="footer">
   {% include '../../widget/system-version.html' %}
 </footer>

+ 1 - 1
lib/views/widget/page_content.html

@@ -15,7 +15,7 @@
   <div class="tab-content">
 
     {% if page %}
-      <script type="text/template" id="raw-text-original">{{ revision.body.toString() }}</script>
+      <script type="text/template" id="raw-text-original">{{ revision.body.toString() | sanitize }}</script>
 
       {# formatted text #}
       <div class="tab-pane {% if not req.body.pageForm %}active{% endif %}" id="revision-body">

+ 1 - 1
lib/views/widget/page_list_and_timeline.html

@@ -33,7 +33,7 @@
             <div class="revision-body wiki"></div>
           </div>
         </div>
-        <script type="text/template">{{ page.revision.body.toString() }}</script>
+        <script type="text/template">{{ page.revision.body.toString() | sanitize }}</script>
       </div>
       <hr>
       {% endfor %}

+ 3 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "3.1.3-RC",
+  "version": "3.1.4-RC",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",
@@ -143,13 +143,14 @@
     "jquery.cookie": "~1.4.1",
     "load-css-file": "^1.0.0",
     "markdown-it": "^8.4.0",
+    "markdown-it-blockdiag": "^1.0.0",
     "markdown-it-emoji": "^1.4.0",
     "markdown-it-footnote": "^3.0.1",
     "markdown-it-mathjax": "^2.0.0",
     "markdown-it-named-headers": "^0.0.4",
     "markdown-it-plantuml": "^1.0.0",
     "markdown-it-task-lists": "^2.1.0",
-    "markdown-it-toc-and-anchor-with-slugid": "^1.1.3",
+    "markdown-it-toc-and-anchor-with-slugid": "^1.1.4",
     "markdown-table": "^1.1.1",
     "metismenu": "^2.7.4",
     "mocha": "^5.0.0",

+ 5 - 1
resource/js/app.js

@@ -30,6 +30,8 @@ import CustomCssEditor  from './components/Admin/CustomCssEditor';
 import CustomScriptEditor from './components/Admin/CustomScriptEditor';
 import CustomHeaderEditor from './components/Admin/CustomHeaderEditor';
 
+import * as entities from 'entities';
+
 if (!window) {
   window = {};
 }
@@ -44,6 +46,7 @@ let pageRevisionCreatedAt = null;
 let pagePath;
 let pageContent = '';
 let markdown = '';
+let pageGrant = null;
 if (mainContent !== null) {
   pageId = mainContent.getAttribute('data-page-id');
   pageRevisionId = mainContent.getAttribute('data-page-revision-id');
@@ -51,8 +54,9 @@ if (mainContent !== null) {
   pagePath = mainContent.attributes['data-path'].value;
   const rawText = document.getElementById('raw-text-original');
   if (rawText) {
-    markdown = rawText.innerHTML;
+    pageContent = rawText.innerHTML;
   }
+  markdown = entities.decodeHTML(pageContent);
 }
 const isLoggedin = document.querySelector('.main-container.nologin') == null;
 

+ 60 - 1
resource/js/legacy/crowi.js

@@ -165,6 +165,50 @@ Crowi.handleKeyCtrlSlashHandler = (event) => {
   event.preventDefault();
 };
 
+Crowi.initSlimScrollForRevisionToc = () => {
+  function getCurrentRevisionTocTop() {
+    const revisionTocElem = document.getElementById('revision-toc');
+    // calculate absolute top of '#revision-toc' element
+    return revisionTocElem.getBoundingClientRect().top;
+  }
+
+  function resetScrollbar(revisionTocTop) {
+    // inner height - revisionTocTop
+    const h = window.innerHeight - revisionTocTop;
+
+    $('#revision-toc-content').slimScroll({
+      railVisible: true,
+      position: 'right',
+      height: h,
+    });
+  }
+
+  // initialize
+  const revisionTocTop = getCurrentRevisionTocTop();
+  resetScrollbar(revisionTocTop);
+
+  /*
+   * set event listener
+   */
+  // resize
+  // TODO turn performance
+  window.addEventListener('resize', (event) => {
+    setTimeout(() => {
+      resetScrollbar(getCurrentRevisionTocTop());
+    }, 200);
+  });
+  // affix on
+  $('#revision-toc').on('affixed.bs.affix', function() {
+    resetScrollbar(getCurrentRevisionTocTop());
+  });
+  // affix off
+  $('#revision-toc').on('affixed-top.bs.affix', function() {
+    // calculate sum of height (.navbar-header + bg-title) + margin-top of .main
+    const sum = 138;
+    resetScrollbar(sum);
+  });
+};
+
 $(function() {
   var config = JSON.parse(document.getElementById('crowi-context-hydrate').textContent || '{}');
 
@@ -430,7 +474,7 @@ $(function() {
         var revisionPath = '#' + id + ' .revision-path';
         /* eslint-enable */
         var pagePath = document.getElementById(id).getAttribute('data-page-path');
-        var markdown = $(contentId).html();
+        var markdown = entities.decodeHTML($(contentId).html());
 
         ReactDOM.render(<Page crowi={crowi} crowiRenderer={growiRendererForTimeline} markdown={markdown} pagePath={pagePath} />, revisionBodyElem);
       });
@@ -529,6 +573,20 @@ $(function() {
       });
     }
 
+    // (function () {
+    //   var timer = 0;
+
+    //   window.onresize = function () {
+    //     if (timer > 0) {
+    //       clearTimeout(timer);
+    //     }
+
+    //     timer = setTimeout(function () {
+    //       DrawScrollbar();
+    //     }, 200);
+    //   };
+    // }());
+
     /*
      * transplanted to React components -- 2017.06.02 Yuki Takei
      *
@@ -890,6 +948,7 @@ window.addEventListener('load', function(e) {
   Crowi.highlightSelectedSection(location.hash);
   Crowi.modifyScrollTop();
   Crowi.setCaretLineAndFocusToEditor();
+  Crowi.initSlimScrollForRevisionToc();
 });
 
 window.addEventListener('hashchange', function(e) {

+ 2 - 0
resource/js/util/GrowiRenderer.js

@@ -15,6 +15,7 @@ import PlantUMLConfigurer from './markdown-it/plantuml';
 import TableConfigurer from './markdown-it/table';
 import TaskListsConfigurer from './markdown-it/task-lists';
 import TocAndAnchorConfigurer from './markdown-it/toc-and-anchor';
+import BlockdiagConfigurer from './markdown-it/blockdiag';
 
 export default class GrowiRenderer {
 
@@ -75,6 +76,7 @@ export default class GrowiRenderer {
       new EmojiConfigurer(crowi),
       new MathJaxConfigurer(crowi),
       new PlantUMLConfigurer(crowi),
+      new BlockdiagConfigurer(crowi),
     ];
 
     // add configurers according to mode

+ 17 - 0
resource/js/util/markdown-it/blockdiag.js

@@ -0,0 +1,17 @@
+export default class BlockdiagConfigurer {
+
+  constructor(crowi) {
+    this.crowi = crowi;
+    const config = crowi.getConfig();
+
+    this.generateSourceUrl = config.env.BLOCKDIAG_URL || 'https://blockdiag-api.com/';
+  }
+
+  configure(md) {
+    //// disable temporary because this breaks /Sandbox -- 2018.06.08 Yuki Takei
+    // md.use(require('markdown-it-blockdiag'), {
+    //   generateSourceUrl: this.generateSourceUrl,
+    //   marker: ':::',
+    // });
+  }
+}

+ 9 - 0
resource/styles/agile-admin/inverse/colors/_apply-colors-light.scss

@@ -24,6 +24,15 @@
   }
 }
 
+/*
+ * GROWI search-top
+ */
+.search-top {
+  .rbt-input.form-control {
+    background-color: rgba($bodycolor, 0.9);
+  }
+}
+
 /*
  * GROWI page list
  */

+ 0 - 5
resource/styles/agile-admin/inverse/colors/blue-night.scss

@@ -47,8 +47,3 @@ $inline-code-bg: #0a121b;
     }
   }
 }
-
-:not(.hljs) > pre:not(.hljs) {
-  color: $bodytext;
-  background-color: $inline-code-bg;
-}

+ 1 - 0
resource/styles/scss/_layout_growi.scss

@@ -7,6 +7,7 @@
     &.affix {
       margin-top: 5px;
       top: calc(46px + 5px);
+      min-width: calc(#{100/12*2%} - #{$grid-gutter-width});  // width of 2column - padding
     }
 
     .revision-toc-content {

+ 0 - 1
resource/styles/scss/_search.scss

@@ -71,7 +71,6 @@
   // see: https://github.com/ericgio/react-bootstrap-typeahead
   .rbt-input.form-control {
     border: none;
-    background-color: rgba(255, 255, 255, 0.9);
     border-radius: 40px;
     border-top-right-radius: 40px;
     border-bottom-right-radius: 40px;

+ 22 - 4
yarn.lock

@@ -4370,10 +4370,24 @@ map-values@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/map-values/-/map-values-1.0.1.tgz#768b8e79c009bf2b64fee806e22a7b1c4190c990"
 
+markdown-it-blockdiag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it-blockdiag/-/markdown-it-blockdiag-1.0.0.tgz#d949ab426e59f948713eb9702ab186a92a572736"
+  dependencies:
+    markdown-it-fence "0.0.2"
+    pako "^1.0.6"
+    paths "^0.1.1"
+    url-join "^4.0.0"
+    utf8-bytes "0.0.1"
+
 markdown-it-emoji@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc"
 
+markdown-it-fence@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/markdown-it-fence/-/markdown-it-fence-0.0.2.tgz#ce1fe95900891603300d9da519aada144d5de9fc"
+
 markdown-it-footnote@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-3.0.1.tgz#7f3730747cacc86e2fe0bf8a17a710f34791517a"
@@ -4396,9 +4410,9 @@ markdown-it-task-lists@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.1.0.tgz#4594f750f70df053d1dad68024388007c1d20783"
 
-markdown-it-toc-and-anchor-with-slugid@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/markdown-it-toc-and-anchor-with-slugid/-/markdown-it-toc-and-anchor-with-slugid-1.1.3.tgz#31eed7da97c3fc06961a16f07cbffa469cc1a288"
+markdown-it-toc-and-anchor-with-slugid@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/markdown-it-toc-and-anchor-with-slugid/-/markdown-it-toc-and-anchor-with-slugid-1.1.4.tgz#92b6d71054d2103720c299bb236497cdaf4797df"
   dependencies:
     clone "^2.1.0"
     uslug "^1.0.4"
@@ -5218,7 +5232,7 @@ pako@1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.3.tgz#5f515b0c6722e1982920ae8005eacb0b7ca73ccf"
 
-pako@~1.0.5:
+pako@^1.0.6, pako@~1.0.5:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
 
@@ -5356,6 +5370,10 @@ path-type@^3.0.0:
   dependencies:
     pify "^3.0.0"
 
+paths@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/paths/-/paths-0.1.1.tgz#9ad909d7f769dd8acb3a1c033c5eef43123d3d17"
+
 pathval@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"