Преглед изворни кода

Merge branch 'master' into inprv/better-input-on-mobile

Yuki Takei пре 7 година
родитељ
комит
822d4eb6d2
34 измењених фајлова са 347 додато и 1591 уклоњено
  1. 7 0
      CHANGES.md
  2. 1 1
      lib/form/admin/securityPassportLdap.js
  3. 6 5
      lib/locales/en-US/translation.json
  4. 6 5
      lib/locales/ja/translation.json
  5. 15 5
      lib/models/page.js
  6. 12 6
      lib/routes/login-passport.js
  7. 8 0
      lib/service/passport.js
  8. 31 5
      lib/util/interceptor-manager.js
  9. 4 4
      lib/views/admin/markdown.html
  10. 9 5
      lib/views/admin/widget/passport/ldap.html
  11. 34 3
      lib/views/widget/passport/ldap-association-tester.html
  12. 1 1
      package.json
  13. 6 0
      resource/js/app.js
  14. 2 4
      resource/js/util/Crowi.js
  15. 36 12
      resource/js/util/interceptor/detach-code-blocks.js
  16. 12 6
      resource/styles/agile-admin/inverse/colors/_apply-colors-dark.scss
  17. 12 0
      resource/styles/agile-admin/inverse/colors/_apply-colors-light.scss
  18. 9 0
      resource/styles/agile-admin/inverse/colors/_apply-colors.scss
  19. 0 152
      resource/styles/agile-admin/inverse/colors/blue-dark.scss
  20. 0 138
      resource/styles/agile-admin/inverse/colors/blue.scss
  21. 1 0
      resource/styles/agile-admin/inverse/colors/default-dark.scss
  22. 0 148
      resource/styles/agile-admin/inverse/colors/gray-dark.scss
  23. 0 138
      resource/styles/agile-admin/inverse/colors/gray.scss
  24. 0 149
      resource/styles/agile-admin/inverse/colors/green-dark.scss
  25. 0 139
      resource/styles/agile-admin/inverse/colors/green.scss
  26. 0 150
      resource/styles/agile-admin/inverse/colors/megna-dark.scss
  27. 0 139
      resource/styles/agile-admin/inverse/colors/megna.scss
  28. 2 16
      resource/styles/agile-admin/inverse/colors/mono-blue.scss
  29. 0 153
      resource/styles/agile-admin/inverse/colors/purple-dark.scss
  30. 0 139
      resource/styles/agile-admin/inverse/colors/purple.scss
  31. 2 0
      resource/styles/agile-admin/inverse/variables.scss
  32. 1 0
      resource/styles/scss/_comment_growi.scss
  33. 78 0
      test/models/page.test.js
  34. 52 68
      yarn.lock

+ 7 - 0
CHANGES.md

@@ -6,8 +6,15 @@ CHANGES
 * Improvement: Group Access Control List - Select group modal
 * Improvement: Auto-format markdown tables which includes multibyte text
 * Improvement: Enable to switch show/hide border for highlight.js
+* Improvement: BindDN field allows also ActiveDirectory styles 
+* Improvement: Show LDAP logs when testing login
+* Improvement: Detach code blocks correctly
+* Fix: Comment body doesn't break long terms
+* Fix: lsx plugin lists up pages that hit by forward match wrongly
+    * Introduced by 3.0.4
 * Support: Upgrade libs
     * elasticsearch
+    * googleapis
 
 ## 3.0.13
 

+ 1 - 1
lib/form/admin/securityPassportLdap.js

@@ -12,7 +12,7 @@ module.exports = form(
   field('settingForm[security:passport-ldap:isUserBind]').trim().toBooleanStrict(),
   field('settingForm[security:passport-ldap:bindDN]').trim()
       // https://regex101.com/r/jK8lpO/1
-      .is(/^(,?[^,=\s]+=[^,=\s]+){1,}$/, 'Bind DN is invalid. <small><a href="https://regex101.com/r/jK8lpO/1">&gt;&gt; Regex</a></small>'),
+      .is(/^(,?[^,=\s]+=[^,=\s]+){1,}$|^[^@\s]+@[^@\s]+$/, 'Bind DN is invalid. <small><a href="https://regex101.com/r/jK8lpO/3">&gt;&gt; Regex</a></small>'),
   field('settingForm[security:passport-ldap:bindDNPassword]'),
   field('settingForm[security:passport-ldap:searchFilter]'),
   field('settingForm[security:passport-ldap:attrMapUsername]'),

+ 6 - 5
lib/locales/en-US/translation.json

@@ -326,7 +326,8 @@
       "search_filter_detail1": "The query used to locate the authenticated user.",
       "search_filter_detail2": "Use <code>&#123;&#123;username&#125;&#125;</code> to reference the username entered in the login page.",
       "search_filter_detail3": "If empty, the filter <code>(uid=&#123;&#123;username&#125;&#125;)</code> is used.",
-      "search_filter_example": "Example to match with 'uid' or 'mail'",
+      "search_filter_example1": "Match with 'uid' or 'mail'",
+      "search_filter_example2": "Match with 'sAMAccountName' for Active Directory",
       "username_detail": "Specification of mappings when creating new users",
       "Treat username matching as identical": "Automatically bind external accounts newly logged in to local accounts when <code>username</code> match",
   		"Treat username matching as identical_warn": "WARNING: Be aware of security because the system treats the same user as a match of <code>username</code>.",
@@ -352,10 +353,10 @@
 
   "markdown_setting": {
     "markdown_rendering": "You can change Markdown rendering settings.",
-    "validate Line Break": "Validate Line Break",
-    "treat_text": "Treat line breaking in the text page as <code>&lt;br&gt;</code> in HTML",
-    "validate_comment": "Validate Line Break in the comment section",
-    "treat_comment": "Treat line breaking in the comment section as <code>&lt;br&gt;</code> in HTML",
+    "Enable Line Break": "Enable Line Break",
+    "Enable Line Break desc": "Treat line break in the text page as <code>&lt;br&gt;</code> in HTML",
+    "Enable Line Break for comment": "Enable Line Break in comment",
+    "Enable Line Break for comment desc": "Treat line break in comment as <code>&lt;br&gt;</code> in HTML",
     "TBD": "(TBD: Markdown function in the comment section has not been implemented yet)"
   },
 

+ 6 - 5
lib/locales/ja/translation.json

@@ -345,7 +345,8 @@
       "search_filter_detail1": "認証されるユーザーを一意に決定するための LDAP フィルタ",
       "search_filter_detail2": "ログイン時のユーザー名を使用するには <code>&#123;&#123;username&#125;&#125;</code> の形式を使用してください。",
       "search_filter_detail3": "空欄の場合 <code>(uid=&#123;&#123;username&#125;&#125;)</code> が使用されます。",
-      "search_filter_example": "'uid' または 'mail' に一致させる場合の例",
+      "search_filter_example1": "'uid' または 'mail' に一致",
+      "search_filter_example2": "'sAMAccountName' に一致 (Active Directory)",
       "username_detail": "新規ユーザーの関連付けを設定",
       "Treat username matching as identical": "新規ログイン時、<code>username</code> が一致したローカルアカウントが存在した場合は自動的に紐付ける",
       "Treat username matching as identical_warn": "WARNING: <code>username</code> の一致を以て同一ユーザーであるとみなすので、セキュリティに注意してください",
@@ -369,10 +370,10 @@
   },
   "markdown_setting": {
     "markdown_rendering": "Markdownレンダリングの設定を変更できます。",
-    "validate Line Break": "Line Break を有効にする",
-    "treat_text": "ページテキスト中の改行を、HTML内で<code>&lt;br&gt;</code>として扱います",
-    "validate_comment": "コメント欄で Line Break を有効にする",
-    "treat_comment": "コメント中の改行を、HTML内で<code>&lt;br&gt;</code>として扱います",
+    "Enable Line Break": "Line Break を有効にする",
+    "Enable Line Break desc": "ページテキスト中の改行を、HTML内で<code>&lt;br&gt;</code>として扱います",
+    "Enable Line Break for comment": "コメント欄で Line Break を有効にする",
+    "Enable Line Break for comment desc": "コメント中の改行を、HTML内で<code>&lt;br&gt;</code>として扱います",
     "TBD": "(TBD: コメント欄の Markdown 化は未だ実装されていません)"
 
   },

+ 15 - 5
lib/models/page.js

@@ -713,6 +713,7 @@ module.exports = function(crowi) {
 
     // ignore other pages than descendants
     path = Page.addSlashOfEnd(path);
+
     // add option to escape the regex strings
     const combinedOption = Object.assign({isRegExpEscapedFromPath: true}, option);
 
@@ -722,8 +723,12 @@ module.exports = function(crowi) {
   /**
    * generate the query to find pages that start with `path`
    *
-   * If `path` has `/` at the end, returns '{path}/*' and '{path}' self.
-   * If `path` doesn't have `/` at the end, returns '{path}*'
+   * (GROWI) If 'isRegExpEscapedFromPath' is true, `path` should have `/` at the end
+   *   -> returns '{path}/*' and '{path}' self.
+   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` has `/` at the end
+   *   -> returns '{path}*'
+   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` doesn't have `/` at the end
+   *   -> returns '{path}*'
    *
    * *option*
    *   - includeDeletedPage -- if true, search deleted pages (default: false)
@@ -735,17 +740,22 @@ module.exports = function(crowi) {
     var includeDeletedPage = option.includeDeletedPage || false;
     var isRegExpEscapedFromPath = option.isRegExpEscapedFromPath || false;
 
+    /*
+     * 1. add condition for finding the page completely match with `path` w/o last slash
+     */
     let pathSlashOmitted = path;
     if (path.match(/\/$/)) {
-      // add condition for finding the page completely match with `path`
       pathSlashOmitted = path.substr(0, path.length -1);
       pathCondition.push({path: pathSlashOmitted});
     }
 
-    // create forward match pattern
+    /*
+     * 2. add decendants
+     */
     var pattern = (isRegExpEscapedFromPath)
-      ? escapeStringRegexp(pathSlashOmitted)  // escape
+      ? escapeStringRegexp(path)  // escape
       : pathSlashOmitted;
+
     var queryReg = new RegExp('^' + pattern);
     pathCondition.push({path: queryReg});
 

+ 12 - 6
lib/routes/login-passport.js

@@ -2,6 +2,7 @@ module.exports = function(crowi, app) {
   'use strict';
 
   var debug = require('debug')('growi:routes:login-passport')
+    , logger = require('@alias/logger')('growi:routes:login-passport')
     , passport = require('passport')
     , config = crowi.getConfig()
     , Config = crowi.model('Config')
@@ -18,7 +19,7 @@ module.exports = function(crowi, app) {
     // update lastLoginAt
     user.updateLastLoginAt(new Date(), (err, userData) => {
       if (err) {
-        console.log(`updateLastLoginAt dumps error: ${err}`);
+        logger.error(`updateLastLoginAt dumps error: ${err}`);
         debug(`updateLastLoginAt dumps error: ${err}`);
       }
     });
@@ -71,8 +72,6 @@ module.exports = function(crowi, app) {
       return next();
     }
 
-    const loginForm = req.body.loginForm;
-
     if (!req.form.isValid) {
       debug('invalid form');
       return res.render('login', {
@@ -89,7 +88,7 @@ module.exports = function(crowi, app) {
       debug('info', info);
 
       if (err) {  // DB Error
-        console.log('LDAP Server Error: ', err);
+        logger.error('LDAP Server Error: ', err);
         req.flash('warningMessage', 'LDAP Server Error occured.');
         return next(); // pass and the flash message is displayed when all of authentications are failed.
       }
@@ -171,16 +170,19 @@ module.exports = function(crowi, app) {
       }
 
       if (err) {  // DB Error
-        console.log('LDAP Server Error: ', err);
+        logger.error('LDAP Server Error: ', err);
         return res.json({
           status: 'warning',
           message: 'LDAP Server Error occured.',
+          err
         });
       }
       if (info && info.message) {
         return res.json({
           status: 'warning',
           message: info.message,
+          ldapConfiguration: req.ldapConfiguration,
+          ldapAccountInfo: req.ldapAccountInfo,
         });
       }
       if (user) {
@@ -189,11 +191,15 @@ module.exports = function(crowi, app) {
           return res.json({
             status: 'warning',
             message: 'The user is found, but that has no groups.',
+            ldapConfiguration: req.ldapConfiguration,
+            ldapAccountInfo: req.ldapAccountInfo,
           });
         }
         return res.json({
           status: 'success',
           message: 'Successfully authenticated.',
+          ldapConfiguration: req.ldapConfiguration,
+          ldapAccountInfo: req.ldapAccountInfo,
         });
       }
     })(req, res, () => {});
@@ -217,7 +223,7 @@ module.exports = function(crowi, app) {
       debug('info', info);
 
       if (err) {  // DB Error
-        console.log('Database Server Error: ', err);
+        logger.error('Database Server Error: ', err);
         req.flash('warningMessage', 'Database Server Error occured.');
         return next(); // pass and the flash message is displayed when all of authentications are failed.
       }

+ 8 - 0
lib/service/passport.js

@@ -115,6 +115,10 @@ class PassportService {
     passport.use(new LdapStrategy(this.getLdapConfigurationFunc(config, {passReqToCallback: true}),
       (req, ldapAccountInfo, done) => {
         debug('LDAP authentication has succeeded', ldapAccountInfo);
+
+        // store ldapAccountInfo to req
+        req.ldapAccountInfo = ldapAccountInfo;
+
         done(null, ldapAccountInfo);
       }
     ));
@@ -212,6 +216,10 @@ class PassportService {
           server: serverOpt,
         }, opts);
         debug('ldap configuration: ', mergedOpts);
+
+        // store configuration to req
+        req.ldapConfiguration = mergedOpts;
+
         callback(null, mergedOpts);
       });
     };

+ 31 - 5
lib/util/interceptor-manager.js

@@ -6,25 +6,51 @@ const logger = require('@alias/logger')('growi:InterceptorManager');
 class InterceptorManager {
 
   constructor() {
+    this.interceptorAndOrders = []; /* [
+                                          {interceptor: instanceA, order: 200 },
+                                          {interceptor: instanceB, order: 100 },
+                                          ...
+                                       ] */
     this.interceptors = [];
   }
 
   /**
    * add an Interceptor
    * @param {BasicInterceptor} interceptor
+   * @param {number} order
    */
-  addInterceptor(interceptor) {
-    this.addInterceptors([interceptor]);
+  addInterceptor(interceptor, order) {
+    this.addInterceptors([interceptor], order);
   }
 
   /**
    * add Interceptors
    * @param {BasicInterceptor[]} interceptors
+   * @param {number} order
    */
-  addInterceptors(interceptors) {
+  addInterceptors(interceptors, order) {
+    let isDefaultOrder = false;
+    if (order == null) {
+      order = 100;
+      isDefaultOrder = true;
+    }
+
     const interceptorIds = interceptors.map((i) => i.getId());
-    logger.debug(`adding interceptors '${interceptorIds}'`);
-    this.interceptors = this.interceptors.concat(interceptors);
+    logger.info(`'addInterceptors' invoked. adding interceptors '${interceptorIds}' at order=${order}${isDefaultOrder ? '(default)' : ''}`);
+
+    this.interceptorAndOrders = this.interceptorAndOrders.concat(
+      interceptors.map(interceptor => {
+        return { interceptor, order };
+      })
+    );
+
+    // sort asc
+    this.interceptorAndOrders.sort((a, b) => a.order - b.order);
+    // store sorted list
+    this.interceptors = this.interceptorAndOrders.map(obj => obj.interceptor);
+
+    const thisInterceptorIds = this.interceptors.map((i) => i.getId());
+    logger.info(`interceptors list has initialized: ${thisInterceptorIds}`);
   }
 
   /**

+ 4 - 4
lib/views/admin/markdown.html

@@ -44,7 +44,7 @@
 
         <div class="form-group">
           <label for="markdownSetting[markdown:isEnabledLinebreaks]" class="col-xs-4 control-label">
-            {{ t('markdown_setting.validate Line Break') }}
+            {{ t('markdown_setting.Enable Line Break') }}
           </label>
           <div class="col-xs-5">
             <div class="btn-group btn-toggle" data-toggle="buttons">
@@ -57,14 +57,14 @@
                     {% if !markdownSetting['markdown:isEnabledLinebreaks'] %}checked{% endif %}> OFF
               </label>
             </div>
-            <p class="help-block">{{ t("markdown_setting.treat_text") }}
+            <p class="help-block">{{ t("markdown_setting.Enable Line Break desc") }}
 </p>
           </div>
         </div>
 
         <div class="form-group">
           <label for="markdownSetting[markdown:isEnabledLinebreaksInComments]" class="col-xs-4 control-label">
-            (TBD)<br>{{ t("markdown_setting.validate_comment") }}
+            (TBD)<br>{{ t("markdown_setting.Enable Line Break for comment") }}
           </label>
           <div class="col-xs-5">
             <div class="btn-group btn-toggle" data-toggle="buttons">
@@ -77,7 +77,7 @@
                     {% if !markdownSetting['markdown:isEnabledLinebreaksInComments'] %}checked{% endif %}> OFF
               </label>
             </div>
-            <p class="help-block">{{ t("markdown_setting.treat_comment") }}<br>{{ t("markdown_setting.TBD") }}</p>
+            <p class="help-block">{{ t("markdown_setting.Enable Line Break for comment desc") }}<br>{{ t("markdown_setting.TBD") }}</p>
           </div>
         </div>
 

+ 9 - 5
lib/views/admin/widget/passport/ldap.html

@@ -62,14 +62,17 @@
               name="settingForm[security:passport-ldap:bindDN]" value="{{ settingForm['security:passport-ldap:bindDN'] || '' }}">
           <p class="help-block passport-ldap-managerbind" {% if isUserBind %}style="display: none;"{% endif %}>
             <small>
-              {{ t("security_setting.ldap.bind_DN_manager_detail") }}
+              {{ t("security_setting.ldap.bind_DN_manager_detail") }}<br>
+              {{ t("security_setting.example") }}1: <code>uid=admin,dc=domain,dc=com</code><br>
+              {{ t("security_setting.example") }}2: <code>admin@domain.com</code>
             </small>
           </p>
           <p class="help-block passport-ldap-userbind" {% if !isUserBind %}style="display: none;"{% endif %}>
             <small>
               {{ t("security_setting.ldap.bind_DN_user_detail1") }}<br>
               {{ t("security_setting.ldap.bind_DN_user_detail2") }}<br>
-              {{ t("security_setting.example") }}: <code>uid={% raw %}{{username}}{% endraw %},dc=domain,dc=com</code><br>
+              {{ t("security_setting.example") }}1: <code>uid={% raw %}{{username}}{% endraw %},dc=domain,dc=com</code><br>
+              {{ t("security_setting.example") }}2: <code>{% raw %}{{username}}{% endraw %}@domain.com</code>
             </small>
           </p>
           </div>
@@ -105,9 +108,10 @@
               {{ t("security_setting.ldap.search_filter_detail3") }}
             </small>
           </p>
-          <p>
+          <p class="help-block">
             <small>
-              {{ t("security_setting.ldap.search_filter_example") }}: <code>(|(uid={% raw %}{{username}}{% endraw %})(mail={% raw %}{{username}}{% endraw %}))</code>
+              {{ t("security_setting.example") }}1 - {{ t("security_setting.ldap.search_filter_example1") }}: <code>(|(uid={% raw %}{{username}}{% endraw %})(mail={% raw %}{{username}}{% endraw %}))</code><br>
+              {{ t("security_setting.example") }}2 - {{ t("security_setting.ldap.search_filter_example2") }}: <code>(sAMAccountName={% raw %}{{username}}{% endraw %})</code>
             </small>
           </p>
         </div>
@@ -307,7 +311,7 @@
 
       <div class="modal-body">
 
-        {% include '../../../widget/passport/ldap-association-tester.html' %}
+        {% include '../../../widget/passport/ldap-association-tester.html' with { showLog: true } %}
 
       </div><!-- /.modal-body -->
 

+ 34 - 3
lib/views/widget/passport/ldap-association-tester.html

@@ -14,12 +14,20 @@
       </div>
     </div>
 
-    <div class="form-group">
-      <button type="button" class="btn btn-default col-xs-offset-5 col-xs-2" onclick="testLdapCredentials()">{{ t('Test') }}</button>
-    </div>
 
   </fieldset>
 
+  {% if showLog %}
+  <fieldset>
+    <h5>Logs</h5>
+    <textarea id="taLogs" class="col-xs-12" rows="4" readonly></textarea>
+  </fieldset>
+  {% endif %}
+
+  <fieldset class="mt-4">
+    <button type="button" class="btn btn-default col-xs-offset-5 col-xs-2" onclick="testLdapCredentials()">{{ t('Test') }}</button>
+  </fieldset>
+
   <script>
     /**
      * test association (ajax)
@@ -44,6 +52,14 @@
           }, 5000);
         }
       }
+      /**
+       * add logs
+       */
+      function addLogs(formId, log) {
+        const textarea = $(`#${formId} #taLogs`);
+        const newLog = `${new Date()} - ${log}\n\n`;
+        textarea.val(`${newLog}${textarea.val()}`);
+      }
 
       var $form = $('#formTestLdapCredentials');
       var $action = '/_api/login/testLdap';
@@ -59,6 +75,21 @@
           else {
             showMessage($id, data.message, data.status);
           }
+
+          // add logs
+          if ('true' === '{{showLog}}') {
+            if (data.err) {
+              addLogs($id, data.err);
+            }
+            if (data.ldapConfiguration) {
+              const prettified = JSON.stringify(data.ldapConfiguration.server, undefined, 4);
+              addLogs($id, `LDAP Configuration : ${prettified}`);
+            }
+            if (data.ldapAccountInfo) {
+              const prettified = JSON.stringify(data.ldapAccountInfo, undefined, 4);
+              addLogs($id, `Retrieved LDAP Account : ${prettified}`);
+            }
+          }
         })
         .fail(function() {
           showMessage($id, 'エラーが発生しました', 'danger');

+ 1 - 1
package.json

@@ -74,7 +74,7 @@
     "express-sanitizer": "^1.0.4",
     "express-session": "~1.15.0",
     "express-webpack-assets": "^0.1.0",
-    "googleapis": "^29.0.0",
+    "googleapis": "^30.0.0",
     "graceful-fs": "^4.1.11",
     "growi-pluginkit": "^1.1.0",
     "i18next": "^11.1.1",

+ 6 - 0
resource/js/app.js

@@ -181,6 +181,11 @@ if (pageEditorOptionsSelectorElem) {
   );
 }
 // render GrantSelector
+/*
+ * Commented out temporary -- 2018.05.21 Yuki Takei
+ *
+ *  err: Uncaught TypeError: Cannot read property 'textContent' of null
+ *
 const userRelatedGroups = JSON.parse(document.getElementById('user-related-group-data').textContent || '{}', (value) => {
   return new UserGroup(value);
 });
@@ -208,6 +213,7 @@ if (pageEditorGrantSelectorElem) {
     pageEditorGrantSelectorElem
   );
 }
+*/
 
 // render for admin
 const customCssEditorElem = document.getElementById('custom-css-editor');

+ 2 - 4
resource/js/util/Crowi.js

@@ -33,10 +33,8 @@ export default class Crowi {
     this.apiRequest = this.apiRequest.bind(this);
 
     this.interceptorManager = new InterceptorManager();
-    this.interceptorManager.addInterceptors([
-      new DetachCodeBlockInterceptor(this),
-      new RestoreCodeBlockInterceptor(this),
-    ]);
+    this.interceptorManager.addInterceptor(new DetachCodeBlockInterceptor(this), 10);       // process as soon as possible
+    this.interceptorManager.addInterceptor(new RestoreCodeBlockInterceptor(this), 900);     // process as late as possible
 
     // FIXME
     this.me = context.me;

+ 36 - 12
resource/js/util/interceptor/detach-code-blocks.js

@@ -3,7 +3,7 @@ import { BasicInterceptor } from 'growi-pluginkit';
 
 class DetachCodeBlockUtil {
   static createReplaceStr(replaceId) {
-    return `<pre>${replaceId}</pre>`;
+    return `<pre class="detached-code-block">${replaceId}</pre>`;
   }
 }
 
@@ -14,6 +14,8 @@ export class DetachCodeBlockInterceptor extends BasicInterceptor {
 
   constructor(crowi) {
     super();
+    this.logger = require('@alias/logger')('growi:DetachCodeBlockInterceptor');
+
     this.crowi = crowi;
     this.crowiForJquery = crowi.getCrowiForJquery();
   }
@@ -22,27 +24,37 @@ export class DetachCodeBlockInterceptor extends BasicInterceptor {
    * @inheritdoc
    */
   isInterceptWhen(contextName) {
-    return (
-      contextName === 'prePreProcess'
-    );
+    return /^prePreProcess|prePostProcess$/.test(contextName);
+  }
+
+  getTargetKey(contextName) {
+    if (contextName === 'prePreProcess') {
+      return 'markdown';
+    }
+    else if (contextName === 'prePostProcess') {
+      return 'parsedHTML';
+    }
   }
 
   /**
    * @inheritdoc
    */
   process(contextName, ...args) {
+    this.logger.debug(`processing: 'contextName'=${contextName}`);
+
     const context = Object.assign(args[0]);   // clone
-    const markdown = context.markdown;
+    const targetKey = this.getTargetKey(contextName);
     /* eslint-disable no-unused-vars */
     const currentPagePath = context.currentPagePath;
     /* eslint-enable */
 
     context.dcbContextMap = {};
 
-    // see: https://regex101.com/r/8PAEcC/3
-    context.markdown = markdown.replace(/((```|~~~)(.|[\r\n])*?(```|~~~))|(`[^\r\n]*?`)/gm, (all) => {
+    // see: https://regex101.com/r/8PAEcC/4
+    context[targetKey] = context[targetKey].replace(/((```|~~~)(.|[\r\n])*?(```|~~~))|(`[^\r\n]*?`)|(<pre>(.|[\r\n])*?<\/pre>)|(<pre\s[^>]*>(.|[\r\n])*?<\/pre>)/gm, (all) => {
       // create ID
       const replaceId = 'dcb-' + this.createRandomStr(8);
+      this.logger.debug(`'replaceId'=${replaceId} : `, all);
 
       // register to context
       let dcbContext = {};
@@ -82,6 +94,8 @@ export class RestoreCodeBlockInterceptor extends BasicInterceptor {
 
   constructor(crowi) {
     super();
+    this.logger = require('@alias/logger')('growi:DetachCodeBlockInterceptor');
+
     this.crowi = crowi;
     this.crowiForJquery = crowi.getCrowiForJquery();
   }
@@ -90,16 +104,26 @@ export class RestoreCodeBlockInterceptor extends BasicInterceptor {
    * @inheritdoc
    */
   isInterceptWhen(contextName) {
-    return (
-      contextName === 'postPreProcess'
-    );
+    return /^postPreProcess|preRenderHtml|preRenderPreviewHtml$/.test(contextName);
+  }
+
+  getTargetKey(contextName) {
+    if (contextName === 'postPreProcess') {
+      return 'markdown';
+    }
+    else if (contextName === 'preRenderHtml' || contextName === 'preRenderPreviewHtml') {
+      return 'parsedHTML';
+    }
   }
 
   /**
    * @inheritdoc
    */
   process(contextName, ...args) {
+    this.logger.debug(`processing: 'contextName'=${contextName}`);
+
     const context = Object.assign(args[0]);   // clone
+    const targetKey = this.getTargetKey(contextName);
 
     // forEach keys of dcbContextMap
     Object.keys(context.dcbContextMap).forEach((replaceId) => {
@@ -107,8 +131,8 @@ export class RestoreCodeBlockInterceptor extends BasicInterceptor {
       let dcbContext = context.dcbContextMap[replaceId];
 
       // replace it with content by using getter function so that the doller sign does not work
-      // see: https://github.com/weseek/crowi-plus/issues/285
-      context.markdown = context.markdown.replace(dcbContext.substituteContent, () => { return dcbContext.content });
+      // see: https://github.com/weseek/growi/issues/285
+      context[targetKey] = context[targetKey].replace(dcbContext.substituteContent, () => { return dcbContext.content });
     });
 
     // resolve

+ 12 - 6
resource/styles/agile-admin/inverse/colors/_apply-colors-dark.scss

@@ -4,12 +4,6 @@
   }
 }
 
-/*
- * Code
- */
-code {
-  background-color: darken($bodycolor, 5%);
-}
 
 /*
  * Button
@@ -156,3 +150,15 @@ legend {
     border-color: $border;
   }
 }
+
+/*
+ * GROWI admin page #themeOptions
+ */
+ .admin-page {
+  #themeOptions {
+    a.active {
+      background-color: darken($themecolor,15%);
+      border-color: darken($themecolor,15%);
+    }
+  }
+}

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

@@ -57,3 +57,15 @@
     border-color: $border;
   }
 }
+
+/*
+ * GROWI admin page #themeOptions
+ */
+ .admin-page {
+  #themeOptions {
+    a.active {
+      background-color: lighten($themecolor,20%);
+      border-color: lighten($themecolor,20%);
+    }
+  }
+}

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

@@ -148,6 +148,15 @@ body{
   color:$white;
 }
 
+/*
+ * code color of inline-code
+ */
+:not(.hljs) > code:not(.hljs) {
+  color: $inline-code-color;
+  background-color: $inline-code-bg;
+}
+
+
 /*
  * Legend
  */

+ 0 - 152
resource/styles/agile-admin/inverse/colors/blue-dark.scss

@@ -1,152 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#008efa;
-$sidebar:#4F5467;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#a6acbc;
-$themecolor:#008efa;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-.top-left-part{
-  background:$sidebar;
-}
-.logo b{
-   
-}
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.07);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$white;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$white;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
- .content-wrapper .sidebar .nav-second-level{
-  li{
-    background:#444859;
-  }
-}  
-@media(min-width:768px) {
-  .content-wrapper { 
-        #side-menu ul, .sidebar #side-menu > li:hover, .sidebar .nav-second-level > li > a{
-              background:#444859;
-         }
-
-   }     
-}
-
-.user-profile .user-pro-body .u-dropdown{
-  color:$sidebar-text;
-}
-/*themecolor*/
-
-.bg-theme {
-  background-color: #707cd2 !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

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

@@ -1,138 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#008efa;
-$sidebar:#fff;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#54667a;
-$themecolor:#008efa;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-
-.logo i{ color:$white;}
-.top-left-part{ 
-  .light-logo{
-    display:inline-block;
-  }
-  .dark-logo{
-    display:none;
-  }
-}
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.03);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$dark;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$dark;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-
-/*themecolor*/
-
-.bg-theme {
-  background-color: #707cd2 !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 1 - 0
resource/styles/agile-admin/inverse/colors/default-dark.scss

@@ -23,6 +23,7 @@ $border: lighten($basecolor, 15%);
 $navbar-border: lighten($border, 10%);
 $active-navbar-border: darken($border, 3%);
 $btn-default-bgcolor: darken($basecolor, 10%);
+$inline-code-bg: darken($bodycolor, 5%);
 
 @import 'apply-colors';
 @import 'apply-colors-dark';

+ 0 - 148
resource/styles/agile-admin/inverse/colors/gray-dark.scss

@@ -1,148 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#a0aec4;
-$sidebar:#4F5467;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#a6acbc;
-$themecolor:#a0aec4;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-.top-left-part{
-  background:$sidebar;
-}
-
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.07);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$white;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$white;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-.content-wrapper .sidebar .nav-second-level{
-  li{
-    background:#444859;
-  }
-}   
-@media(min-width:768px) {
-  .content-wrapper { 
-        #side-menu ul, .sidebar #side-menu > li:hover, .sidebar .nav-second-level > li > a{
-              background:#444859;
-         }
-   }     
-}
-.user-profile .user-pro-body .u-dropdown{
-  color:$sidebar-text;
-}
-/*themecolor*/
-
-.bg-theme {
-  background-color: $danger !important;
-}
-.bg-theme-dark {
-  background-color: $megna !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 138
resource/styles/agile-admin/inverse/colors/gray.scss

@@ -1,138 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#a0aec4;
-$sidebar:#fff;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#54667a;
-$themecolor:#a0aec4;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-
-.top-left-part{ 
-  .light-logo{
-    display:inline-block;
-  }
-  .dark-logo{
-    display:none;
-  }
-}
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.03);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$dark;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$dark;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-/*themecolor*/
-
-.bg-theme {
-  background-color: $danger !important;
-}
-.bg-theme-dark {
-  background-color: $megna !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 149
resource/styles/agile-admin/inverse/colors/green-dark.scss

@@ -1,149 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#00c292;
-$sidebar:#4F5467;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#a6acbc;
-$themecolor:#00c292;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-.top-left-part{
-  background:$sidebar;
-}
-.logo b{
-   
-}
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.07);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$white;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$white;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-.content-wrapper .sidebar .nav-second-level{
-  li{
-    background:#444859;
-  }
-}   
-@media(min-width:768px) {
-  .content-wrapper { 
-        #side-menu ul, .sidebar #side-menu > li:hover, .sidebar .nav-second-level > li > a{
-              background:#444859;
-         }
-   }     
-}
-.user-profile .user-pro-body .u-dropdown{
-  color:$sidebar-text;
-}
-/*themecolor*/
-
-.bg-theme {
-  background-color: #6e8680 !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 139
resource/styles/agile-admin/inverse/colors/green.scss

@@ -1,139 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#00c292;
-$sidebar:#fff;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#54667a;
-$themecolor:#00c292;
-$dark-themecolor:#4F5467;
-
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-
-.logo i{ color:$white;}
-.top-left-part{ 
-  .light-logo{
-    display:inline-block;
-  }
-  .dark-logo{
-    display:none;
-  }
-}
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.03);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$dark;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$dark;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-
-/*themecolor*/
-
-.bg-theme {
-  background-color: #6e8680 !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 150
resource/styles/agile-admin/inverse/colors/megna-dark.scss

@@ -1,150 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#00b5c2;
-$sidebar:#4F5467;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#a6acbc;
-$themecolor:#00b5c2;
-$dark-themecolor:#4F5467;
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-.top-left-part{
-  background:$sidebar;
-}
-.logo b{
-   
-}
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.07);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$white;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$white;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-.content-wrapper .sidebar .nav-second-level{
-  li{
-    background:#444859;
-  }
-}   
-@media(min-width:768px) {
-  .content-wrapper { 
-        #side-menu ul, .sidebar #side-menu > li:hover, .sidebar .nav-second-level > li > a{
-              background:#444859;
-         }
-   }     
-}
-
-.user-profile .user-pro-body .u-dropdown{
-  color:$sidebar-text;
-}
-/*themecolor*/
-
-.bg-theme {
-  background-color: $danger !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 139
resource/styles/agile-admin/inverse/colors/megna.scss

@@ -1,139 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#00b5c2;
-$sidebar:#fff;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#54667a;
-$themecolor:#00b5c2;
-$dark-themecolor:#4F5467;
-
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-
-.logo i{ color:$white;}
-.top-left-part{ 
-  .light-logo{
-    display:inline-block;
-  }
-  .dark-logo{
-    display:none;
-  }
-}
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.03);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$dark;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$dark;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-
-/*themecolor*/
-
-.bg-theme {
-  background-color: $danger !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 2 - 16
resource/styles/agile-admin/inverse/colors/mono-blue.scss

@@ -21,17 +21,13 @@ $info: lighten($themecolor,20%);
 $logo-mark-fill: lighten(desaturate($topbar, 30%), 20%);
 $wikilinktext: lighten($themecolor, 20%);
 $wikilinktext-hover: lighten($wikilinktext, 20%);
+$inline-code-color: $subthemecolor;
+$inline-code-bg: lighten($subthemecolor,70%);
 
 @import 'apply-colors';
 @import 'apply-colors-light';
 
 
-// change color of inline-code (default: red)
-:not(.hljs) > code:not(.hljs) {
-  background-color: lighten($subthemecolor,70%);
-  color: $subthemecolor;
-}
-
 // change color of highlighted header in wiki (default: orange)
 .wiki {
   .code-line.revision-head.highlighted {
@@ -39,13 +35,3 @@ $wikilinktext-hover: lighten($wikilinktext, 20%);
     color: $themelight;
   }
 }
-
-// change color of surrounding border of theme option icon at admin/customize (default: green)
-.admin-page {
-  #themeOptions {
-    a.active {
-      background-color: lighten($themecolor,20%);
-      border-color: lighten($themecolor,20%);
-    }
-  }
-}

+ 0 - 153
resource/styles/agile-admin/inverse/colors/purple-dark.scss

@@ -1,153 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#2c5ca9;
-$sidebar:#4F5467;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#a6acbc;
-$themecolor:#2c5ca9;
-$dark-themecolor:#4F5467;
-
-
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-.top-left-part{
-  background:$sidebar;
-}
-.logo b{
-   
-}
-.logo i{ color:$white;}
-
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.07);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$white;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$white;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-.content-wrapper .sidebar .nav-second-level{
-  li{
-    background:#444859;
-  }
-}   
-@media(min-width:768px) {
-  .content-wrapper { 
-        #side-menu ul, .sidebar #side-menu > li:hover, .sidebar .nav-second-level > li > a{
-              background:#444859;
-         }
-
-   }     
-}
-
-.user-profile .user-pro-body .u-dropdown{
-  color:$sidebar-text;
-}
-/*themecolor*/
-
-.bg-theme {
-  background-color: $info !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 0 - 139
resource/styles/agile-admin/inverse/colors/purple.scss

@@ -1,139 +0,0 @@
-@import "../variables.scss";
-
-/*Just change your choise color here its theme Colors*/
-
-$topbar:#2c5ca9;
-$sidebar:#fff;
-$bodycolor:#f1f2f7;
-$headingtext: #2b2b2b;
-$bodytext: #686868;
-$sidebar-text:#54667a;
-$themecolor:#2c5ca9;
-$dark-themecolor:#4F5467;
-
-
-
-body{
-  background:$sidebar;
-}
-
-/*Top Header Part*/
-
-.logo i{ color:$white;}
-.top-left-part{ 
-  .light-logo{
-    display:inline-block;
-  }
-  .dark-logo{
-    display:none;
-  }
-}
-.navbar-header{ 
-     background:$topbar;
-}
-.navbar-top-links > li > a{
-    color:$white;
-}
-
-
-
-/*Right panel*/
-.right-sidebar .rpanel-title{
-  background:$themecolor;
-}
-
-/*Bread Crumb*/
-.bg-title .breadcrumb .active{
-    color:$themecolor;
-}
-.bg-title{
-  
-}
-
-/*Sidebar*/
-
-.sidebar {
-    background:$sidebar;
-    box-shadow:1px 0px 20px rgba(0, 0, 0, 0.08);
-  .label-custom{
-      background:$megna;
-  }  
-}
-#side-menu li a{
-    color:$sidebar-text;
-}
-#side-menu li a{
-    color:$sidebar-text;
-  border-left:0px solid $sidebar;
-}
-
-#side-menu > li > a {
-    &:hover, &:focus{
-        background:rgba(0, 0, 0, 0.03);
-    }
-   &.active {
-            border-left:3px solid $themecolor;
-            color:$dark;
-            
-            font-weight:500;
-        i{
-          color:$themecolor;
-        }
-        }
-
-}
-#side-menu ul > li > a {
-    &:hover{
-        color:$themecolor;
-        
-    }
-    &.active{
-     color:$dark;
-     font-weight:500;
-    }
-}
-.sidebar #side-menu .user-pro{
-  .nav-second-level a:hover{
-          color:$themecolor;
-        }
-  }
-
-/*themecolor*/
-
-.bg-theme {
-  background-color: $info !important;
-}
-.bg-theme-dark {
-  background-color: $themecolor !important;
-}
-
-/*Chat widget*/
-.chat-list .odd .chat-text{
-    background:$themecolor;
-}
-/*Button*/
-.btn-custom{
-  background:$themecolor;
-  border:1px solid $themecolor;
-  color:$white;
-  &:hover{
-    background:$themecolor;
-    opacity:0.8;
-    color:$white;
-    border:1px solid $themecolor;
-  }
-}
-/*Custom tab*/
-.customtab li.active a, .customtab li.active a:hover,  .customtab li.active a:focus{
- border-bottom:2px solid $themecolor;
- color:$themecolor;
-}
-.tabs-vertical li.active a, .tabs-vertical li.active a:hover,  .tabs-vertical li.active a:focus{
-  background:$themecolor;
-  border-right:2px solid $themecolor;
-}
-/*Nav-pills*/
-.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover{
-  background:$themecolor;
-  color:$white;
-}

+ 2 - 0
resource/styles/agile-admin/inverse/variables.scss

@@ -54,6 +54,8 @@ $dark-text:#848a96 !default;
 $navbar-border: #ccc !default;
 $active-navbar-border: lighten($navbar-border, 10%) !default;
 $btn-default-bgcolor: darken(#fff, 10%) !default;
+$inline-code-color: #c7254e !default;
+$inline-code-bg: #f9f2f4 !default;
 
 /*Border radius*/
 $radius: 0 !default;

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

@@ -58,6 +58,7 @@
     // コメント本文
     .page-comment-body {
       margin-bottom: 0.5em;
+      word-wrap: break-word;
     }
 
     .page-comment-meta {

+ 78 - 0
test/models/page.test.js

@@ -74,6 +74,21 @@ describe('Page', () => {
           grantedUsers: [],
           creator: testUser1,
         },
+        {
+          path: '/page1',
+          grant: Page.GRANT_PUBLIC,
+          creator: testUser0,
+        },
+        {
+          path: '/page1/child1',
+          grant: Page.GRANT_PUBLIC,
+          creator: testUser0,
+        },
+        {
+          path: '/page2',
+          grant: Page.GRANT_PUBLIC,
+          creator: testUser0,
+        },
       ];
 
       return testDBUtil.generateFixture(conn, 'Page', fixture);
@@ -394,4 +409,67 @@ describe('Page', () => {
     });
   });
 
+  context('generateQueryToListByStartWith', () => {
+    it('should return only /page/', done => {
+      const user = createdUsers[0];
+      Page.generateQueryToListByStartWith('/page/', user, { isRegExpEscapedFromPath: true })
+      .then(pages => {
+        // assert length
+        expect(pages.length).to.equal(1);
+        // assert paths
+        const pagePaths = pages.map(page => page.path);
+        expect(pagePaths).to.include.members(['/page/for/extended'])
+        done();
+      })
+      .catch((err) => {
+        done(err);
+      });
+    });
+    it('should return only /page1/', done => {
+      const user = createdUsers[0];
+      Page.generateQueryToListByStartWith('/page1/', user, { isRegExpEscapedFromPath: true })
+      .then(pages => {
+        // assert length
+        expect(pages.length).to.equal(2);
+        // assert paths
+        const pagePaths = pages.map(page => page.path);
+        expect(pagePaths).to.include.members(['/page1', '/page1/child1'])
+        done();
+      })
+      .catch((err) => {
+        done(err);
+      });
+    });
+    it('should return pages which starts with /page', done => {
+      const user = createdUsers[0];
+      Page.generateQueryToListByStartWith('/page', user, {})
+      .then(pages => {
+        // assert length
+        expect(pages.length).to.equal(4);
+        // assert paths
+        const pagePaths = pages.map(page => page.path);
+        expect(pagePaths).to.include.members(['/page/for/extended', '/page1', '/page1/child1', '/page2'])
+        done();
+      })
+      .catch((err) => {
+        done(err);
+      });
+    });
+    it('should process with regexp', done => {
+      const user = createdUsers[0];
+      Page.generateQueryToListByStartWith('/page\\d{1}/', user, {})
+      .then(pages => {
+        // assert length
+        expect(pages.length).to.equal(3);
+        // assert paths
+        const pagePaths = pages.map(page => page.path);
+        expect(pagePaths).to.include.members(['/page1', '/page1/child1', '/page2'])
+        done();
+      })
+      .catch((err) => {
+        done(err);
+      });
+    });
+  });
+
 });

+ 52 - 68
yarn.lock

@@ -133,9 +133,11 @@ after@0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
 
-agentkeepalive@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
+agentkeepalive@^3.4.1:
+  version "3.4.1"
+  resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.4.1.tgz#aa95aebc3a749bca5ed53e3880a09f5235b48f0c"
+  dependencies:
+    humanize-ms "^1.2.1"
 
 ajv-keywords@^2.1.0:
   version "2.1.1"
@@ -454,13 +456,6 @@ aws4@^1.2.1, aws4@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
 
-axios@^0.17.0, axios@^0.17.1:
-  version "0.17.1"
-  resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d"
-  dependencies:
-    follow-redirects "^1.2.5"
-    is-buffer "^1.1.5"
-
 axios@^0.18.0:
   version "0.18.0"
   resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
@@ -2315,16 +2310,13 @@ ejs@^2.5.6:
   version "2.5.7"
   resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
 
-elasticsearch@^14.0.0:
-  version "14.0.0"
-  resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-14.0.0.tgz#560317ca87121a73c0895818ae291f5553857bda"
+elasticsearch@^15.0.0:
+  version "15.0.0"
+  resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-15.0.0.tgz#d888ceb858bba30221b68698d72c54bdcfdf2fba"
   dependencies:
-    agentkeepalive "^2.2.0"
+    agentkeepalive "^3.4.1"
     chalk "^1.0.0"
-    lodash "2.4.2"
-    lodash.get "^4.4.2"
-    lodash.isempty "^4.4.0"
-    lodash.trimend "^4.5.1"
+    lodash "^4.17.10"
 
 electron-releases@^2.1.0:
   version "2.1.0"
@@ -2963,12 +2955,6 @@ flatten@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
 
-follow-redirects@^1.2.5:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.3.0.tgz#f684871fc116d2e329fda55ef67687f4fabc905c"
-  dependencies:
-    debug "^3.1.0"
-
 follow-redirects@^1.3.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.4.1.tgz#d8120f4518190f55aac65bb6fc7b85fcd666d6aa"
@@ -3104,13 +3090,13 @@ gaze@^1.0.0:
   dependencies:
     globule "^1.0.0"
 
-gcp-metadata@^0.6.0:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-0.6.1.tgz#62d54871fc6aeeac6a688e094abc886cb7aaacd0"
+gcp-metadata@^0.6.3:
+  version "0.6.3"
+  resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-0.6.3.tgz#4550c08859c528b370459bd77a7187ea0bdbc4ab"
   dependencies:
-    axios "^0.17.1"
+    axios "^0.18.0"
     extend "^3.0.1"
-    retry-axios "0.3.0"
+    retry-axios "0.3.2"
 
 generate-function@^2.0.0:
   version "2.0.0"
@@ -3211,16 +3197,16 @@ good-listener@^1.2.2:
   dependencies:
     delegate "^3.1.2"
 
-google-auth-library@^1.3.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-1.3.1.tgz#a0456166c9538ee062c51b8e70765a5a0e13e757"
+google-auth-library@^1.4.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-1.5.0.tgz#d9068f8bad9017224a4c41abcdcb6cf6a704e83b"
   dependencies:
     axios "^0.18.0"
-    gcp-metadata "^0.6.0"
-    gtoken "^2.1.0"
+    gcp-metadata "^0.6.3"
+    gtoken "^2.3.0"
     jws "^3.1.4"
     lodash.isstring "^4.0.1"
-    lru-cache "^4.1.1"
+    lru-cache "^4.1.2"
     retry-axios "^0.3.2"
 
 google-p12-pem@^1.0.0:
@@ -3230,11 +3216,11 @@ google-p12-pem@^1.0.0:
     node-forge "^0.7.1"
     pify "^3.0.0"
 
-googleapis@^29.0.0:
-  version "29.0.0"
-  resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-29.0.0.tgz#b1b2c080b7c5722621671f732a278a879758f4dd"
+googleapis@^30.0.0:
+  version "30.0.0"
+  resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-30.0.0.tgz#4673ba34878217539ca5aa4216fef4db6c247649"
   dependencies:
-    google-auth-library "^1.3.1"
+    google-auth-library "^1.4.0"
     pify "^3.0.0"
     qs "^6.5.1"
     url-template "^2.0.8"
@@ -3256,14 +3242,14 @@ growly@^1.2.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
 
-gtoken@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-2.1.0.tgz#e65028d32d1d52eeb17b00f85ef0f7484f0fd36f"
+gtoken@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-2.3.0.tgz#4e0ffc16432d7041a1b3dbc1d97aac17a5dc964a"
   dependencies:
-    axios "^0.17.0"
+    axios "^0.18.0"
     google-p12-pem "^1.0.0"
-    jws "^3.0.0"
-    mime "^2.0.3"
+    jws "^3.1.4"
+    mime "^2.2.0"
     pify "^3.0.0"
 
 gzip-size@^3.0.0:
@@ -3469,6 +3455,12 @@ https-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
 
+humanize-ms@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+  dependencies:
+    ms "^2.0.0"
+
 i18next-express-middleware@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.1.1.tgz#9204f28c8800ac3bff87fbee01945367956f349c"
@@ -3973,7 +3965,7 @@ jwa@^1.1.4:
     ecdsa-sig-formatter "1.0.9"
     safe-buffer "^5.0.1"
 
-jws@^3.0.0, jws@^3.1.4:
+jws@^3.1.4:
   version "3.1.4"
   resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.4.tgz#f9e8b9338e8a847277d6444b1464f61880e050a2"
   dependencies:
@@ -4233,10 +4225,6 @@ lodash.isarray@^3.0.0:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
 
-lodash.isempty@^4.4.0:
-  version "4.4.0"
-  resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
-
 lodash.isfinite@^3.3.2:
   version "3.3.2"
   resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3"
@@ -4319,18 +4307,10 @@ lodash.toplainobject@^3.0.0:
     lodash._basecopy "^3.0.0"
     lodash.keysin "^3.0.0"
 
-lodash.trimend@^4.5.1:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/lodash.trimend/-/lodash.trimend-4.5.1.tgz#12804437286b98cad8996b79414e11300114082f"
-
 lodash.uniq@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 
-lodash@2.4.2:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e"
-
 lodash@^3.10.1:
   version "3.10.1"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
@@ -4343,6 +4323,10 @@ lodash@^4.15.0, lodash@^4.2.0, lodash@^4.3.0:
   version "4.17.5"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
 
+lodash@^4.17.10:
+  version "4.17.10"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
 lolex@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
@@ -4368,14 +4352,14 @@ loud-rejection@^1.0.0:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
 
-lru-cache@4.1.x:
+lru-cache@4.1.x, lru-cache@^4.1.2:
   version "4.1.3"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
   dependencies:
     pseudomap "^1.0.2"
     yallist "^2.1.2"
 
-lru-cache@^4.0.1, lru-cache@^4.0.2, lru-cache@^4.1.1:
+lru-cache@^4.0.1, lru-cache@^4.0.2:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
   dependencies:
@@ -4604,9 +4588,9 @@ mime@1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
 
-mime@^2.0.3:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.2.0.tgz#161e541965551d3b549fa1114391e3a3d55b923b"
+mime@^2.2.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369"
 
 mimic-fn@^1.0.0:
   version "1.1.0"
@@ -4778,6 +4762,10 @@ ms@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
 
+ms@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+
 multer@~1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/multer/-/multer-1.3.0.tgz#092b2670f6846fa4914965efc8cf94c20fec6cd2"
@@ -6413,11 +6401,7 @@ restore-cursor@^2.0.0:
     onetime "^2.0.0"
     signal-exit "^3.0.2"
 
-retry-axios@0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/retry-axios/-/retry-axios-0.3.0.tgz#7858ad369872d6acaf05fd97b0490969c9c35ee2"
-
-retry-axios@^0.3.2:
+retry-axios@0.3.2, retry-axios@^0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/retry-axios/-/retry-axios-0.3.2.tgz#5757c80f585b4cc4c4986aa2ffd47a60c6d35e13"