Просмотр исходного кода

Merge remote-tracking branch 'origin/imprv/abolish-old-config-api' into imprv/abolish-old-config-api-plugin

mizozobu 6 лет назад
Родитель
Сommit
62e0c8234a

+ 1 - 1
src/client/js/app.js

@@ -121,7 +121,7 @@ if (pageContainer.state.path != null) {
   componentMappings = Object.assign({
     // eslint-disable-next-line quote-props
     'page': <Page />,
-    'revision-path':  <RevisionPath pageId={pageContainer.state.pageId} pagePath={pageContainer.state.path} crowi={appContainer} />,
+    'revision-path': <RevisionPath behaviorType={appContainer.config.behaviorType} pageId={pageContainer.state.pageId} pagePath={pageContainer.state.path} />,
     'tag-label':  <TagLabels />,
   }, componentMappings);
 }

+ 3 - 3
src/client/js/components/Page/RevisionPath.jsx

@@ -26,8 +26,8 @@ class RevisionPath extends React.Component {
     this.setState({ isListPage });
 
     // whether set link to '/'
-    const behaviorType = this.props.crowi.getConfig().behaviorType;
-    const isLinkToListPage = (!behaviorType || behaviorType === 'crowi');
+    const { behaviorType } = this.props;
+    const isLinkToListPage = (behaviorType === 'crowi');
     this.setState({ isLinkToListPage });
 
     // generate pages obj
@@ -127,7 +127,7 @@ class RevisionPath extends React.Component {
 
 RevisionPath.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  crowi: PropTypes.object.isRequired,
+  behaviorType: PropTypes.string.isRequired,
   pagePath: PropTypes.string.isRequired,
   pageId: PropTypes.string,
 };

+ 18 - 6
src/server/crowi/index.js

@@ -79,14 +79,11 @@ Crowi.prototype.init = async function() {
   await this.setupSessionConfig();
   await this.setupConfigManager();
 
-  // passport depends on appService
-  // initialize services first
-  // とりあえず新しく作ったサービスクラスのみ上に移した。
+  // customizeService depends on AppService and XssService
+  // passportService depends on appService
   await Promise.all([
-    this.setUpSlacklNotification(),
-    this.setUpXss(),
-    this.setUpAcl(),
     this.setUpApp(),
+    this.setUpXss(),
   ]);
 
   await Promise.all([
@@ -97,6 +94,9 @@ Crowi.prototype.init = async function() {
     this.setupSlack(),
     this.setupCsrf(),
     this.setUpGlobalNotification(),
+    this.setUpSlacklNotification(),
+    this.setUpAcl(),
+    this.setUpCustomize(),
     this.setUpRestQiitaAPI(),
   ]);
 };
@@ -478,6 +478,18 @@ Crowi.prototype.setUpAcl = function() {
   }
 };
 
+/**
+ * setup CustomizeService
+ */
+Crowi.prototype.setUpCustomize = function() {
+  const CustomizeService = require('../service/customize');
+  if (this.customizeService == null) {
+    this.customizeService = new CustomizeService(this.configManager, this.appService, this.xssService);
+    this.customizeService.initCustomCss();
+    this.customizeService.initCustomTitle();
+  }
+};
+
 /**
  * setup AppService
  */

+ 21 - 116
src/server/models/config.js

@@ -6,7 +6,6 @@
 module.exports = function(crowi) {
   const mongoose = require('mongoose');
   const debug = require('debug')('growi:models:config');
-  const uglifycss = require('uglifycss');
   const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
 
   const SECURITY_RESTRICT_GUEST_MODE_DENY = 'Deny';
@@ -38,7 +37,6 @@ module.exports = function(crowi) {
     // overwrite
     config['app:installed'] = true;
     config['app:fileUpload'] = true;
-    config['security:isEnabledPassport'] = true;
     config['customize:behavior'] = 'growi';
     config['customize:layout'] = 'growi';
     config['customize:isSavedStatesOfTabChanges'] = false;
@@ -53,7 +51,7 @@ module.exports = function(crowi) {
     /* eslint-disable key-spacing */
     return {
       'app:installed'     : false,
-      'app:confidential'  : '',
+      'app:confidential'  : undefined,
 
       'app:fileUpload'    : false,
       'app:globalLang'    : 'en-US',
@@ -89,24 +87,24 @@ module.exports = function(crowi) {
 
       'aws:bucket'          : 'growi',
       'aws:region'          : 'ap-northeast-1',
-      'aws:accessKeyId'     : '',
-      'aws:secretAccessKey' : '',
+      'aws:accessKeyId'     : undefined,
+      'aws:secretAccessKey' : undefined,
 
-      'mail:from'         : '',
-      'mail:smtpHost'     : '',
-      'mail:smtpPort'     : '',
-      'mail:smtpUser'     : '',
-      'mail:smtpPassword' : '',
+      'mail:from'         : undefined,
+      'mail:smtpHost'     : undefined,
+      'mail:smtpPort'     : undefined,
+      'mail:smtpUser'     : undefined,
+      'mail:smtpPassword' : undefined,
 
-      'google:clientId'     : '',
-      'google:clientSecret' : '',
+      'google:clientId'     : undefined,
+      'google:clientSecret' : undefined,
 
       'plugin:isEnabledPlugins' : true,
 
-      'customize:css' : '',
-      'customize:script' : '',
-      'customize:header' : '',
-      'customize:title' : '',
+      'customize:css' : undefined,
+      'customize:script' : undefined,
+      'customize:header' : undefined,
+      'customize:title' : undefined,
       'customize:highlightJsStyle' : 'github',
       'customize:highlightJsStyleBorder' : false,
       'customize:theme' : 'default',
@@ -117,10 +115,10 @@ module.exports = function(crowi) {
       'customize:isEnabledAttachTitleHeader' : false,
       'customize:showRecentCreatedNumber' : 10,
 
-      'importer:esa:team_name': '',
-      'importer:esa:access_token': '',
-      'importer:qiita:team_name': '',
-      'importer:qiita:access_token': '',
+      'importer:esa:team_name': undefined,
+      'importer:esa:access_token': undefined,
+      'importer:qiita:team_name': undefined,
+      'importer:qiita:access_token': undefined,
     };
     /* eslint-enable key-spacing */
   }
@@ -134,15 +132,15 @@ module.exports = function(crowi) {
       'markdown:isEnabledLinebreaks': false,
       'markdown:isEnabledLinebreaksInComments': true,
       'markdown:presentation:pageBreakSeparator': 1,
-      'markdown:presentation:pageBreakCustomSeparator': '',
+      'markdown:presentation:pageBreakCustomSeparator': undefined,
     };
   }
 
   function getDefaultNotificationConfigs() {
     return {
       'slack:isIncomingWebhookPrioritized': false,
-      'slack:incomingWebhookUrl': '',
-      'slack:token': '',
+      'slack:incomingWebhookUrl': undefined,
+      'slack:token': undefined,
     };
   }
 
@@ -426,99 +424,6 @@ module.exports = function(crowi) {
     }
   };
 
-  /**
-   * initialize custom css strings
-   */
-  configSchema.statics.initCustomCss = function(config) {
-    const key = 'customize:css';
-    const rawCss = getValueForCrowiNS(config, key);
-    // uglify and store
-    this._customCss = uglifycss.processString(rawCss);
-  };
-
-  configSchema.statics.customCss = function(config) {
-    return this._customCss;
-  };
-
-  configSchema.statics.initCustomScript = function(config) {
-    const key = 'customize:script';
-    const rawScript = getValueForCrowiNS(config, key);
-    // store as is
-    this._customScript = rawScript;
-  };
-
-  configSchema.statics.customScript = function(config) {
-    return this._customScript;
-  };
-
-  configSchema.statics.customHeader = function(config) {
-    const key = 'customize:header';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.theme = function(config) {
-    const key = 'customize:theme';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.customTitle = function(config, page) {
-    validateCrowi();
-
-    const key = 'customize:title';
-    let customTitle = getValueForCrowiNS(config, key);
-
-    if (customTitle == null || customTitle.trim().length === 0) {
-      customTitle = '{{page}} - {{sitename}}';
-    }
-
-    // replace
-    customTitle = customTitle
-      .replace('{{sitename}}', this.appTitle(config))
-      .replace('{{page}}', page);
-
-    return crowi.xss.process(customTitle);
-  };
-
-  configSchema.statics.behaviorType = function(config) {
-    const key = 'customize:behavior';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.layoutType = function(config) {
-    const key = 'customize:layout';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.highlightJsStyle = function(config) {
-    const key = 'customize:highlightJsStyle';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.highlightJsStyleBorder = function(config) {
-    const key = 'customize:highlightJsStyleBorder';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.isEnabledTimeline = function(config) {
-    const key = 'customize:isEnabledTimeline';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.isSavedStatesOfTabChanges = function(config) {
-    const key = 'customize:isSavedStatesOfTabChanges';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.isEnabledAttachTitleHeader = function(config) {
-    const key = 'customize:isEnabledAttachTitleHeader';
-    return getValueForCrowiNS(config, key);
-  };
-
-  configSchema.statics.showRecentCreatedNumber = function(config) {
-    const key = 'customize:showRecentCreatedNumber';
-    return getValueForCrowiNS(config, key);
-  };
-
   configSchema.statics.fileUploadEnabled = function(config) {
     const Config = this;
 

+ 17 - 12
src/server/routes/page.js

@@ -2,7 +2,10 @@
 module.exports = function(crowi, app) {
   const debug = require('debug')('growi:routes:page');
   const logger = require('@alias/logger')('growi:routes:page');
+  const swig = require('swig-templates');
+
   const pathUtils = require('growi-commons').pathUtils;
+
   const Page = crowi.model('Page');
   const User = crowi.model('User');
   const Config = crowi.model('Config');
@@ -10,10 +13,12 @@ module.exports = function(crowi, app) {
   const Bookmark = crowi.model('Bookmark');
   const PageTagRelation = crowi.model('PageTagRelation');
   const UpdatePost = crowi.model('UpdatePost');
+
   const ApiResponse = require('../util/apiResponse');
-  const interceptorManager = crowi.getInterceptorManager();
-  const swig = require('swig-templates');
   const getToday = require('../util/getToday');
+
+  const configManager = crowi.configManager;
+  const interceptorManager = crowi.getInterceptorManager();
   const globalNotificationService = crowi.getGlobalNotificationService();
 
   const actions = {};
@@ -303,9 +308,9 @@ module.exports = function(crowi, app) {
    */
   /* eslint-disable no-else-return */
   actions.showPageWithEndOfSlash = function(req, res, next) {
-    const behaviorType = Config.behaviorType(config);
+    const behaviorType = configManager.getConfig('crowi', 'customize:behavior');
 
-    if (!behaviorType || behaviorType === 'crowi') {
+    if (behaviorType === 'crowi') {
       return showPageListForCrowiBehavior(req, res, next);
     }
     else {
@@ -327,10 +332,10 @@ module.exports = function(crowi, app) {
       return showPageForPresentation(req, res, next);
     }
 
-    const behaviorType = Config.behaviorType(config);
+    const behaviorType = configManager.getConfig('crowi', 'customize:behavior');
 
     // check whether this page has portal page
-    if (!behaviorType || behaviorType === 'crowi') {
+    if (behaviorType === 'crowi') {
       const portalPagePath = pathUtils.addTrailingSlash(getPathFromRequest(req));
       const hasPortalPage = await Page.count({ path: portalPagePath }) > 0;
 
@@ -349,9 +354,9 @@ module.exports = function(crowi, app) {
    */
   /* eslint-disable no-else-return */
   actions.trashPageListShowWrapper = function(req, res) {
-    const behaviorType = Config.behaviorType(config);
+    const behaviorType = configManager.getConfig('crowi', 'customize:behavior');
 
-    if (!behaviorType || behaviorType === 'crowi') {
+    if (behaviorType === 'crowi') {
       // Crowi behavior for '/trash/*'
       return actions.deletedPageListShow(req, res);
     }
@@ -367,9 +372,9 @@ module.exports = function(crowi, app) {
    */
   /* eslint-disable no-else-return */
   actions.trashPageShowWrapper = function(req, res) {
-    const behaviorType = Config.behaviorType(config);
+    const behaviorType = configManager.getConfig('crowi', 'customize:behavior');
 
-    if (!behaviorType || behaviorType === 'crowi') {
+    if (behaviorType === 'crowi') {
       // redirect to '/trash/'
       return res.redirect('/trash/');
     }
@@ -385,9 +390,9 @@ module.exports = function(crowi, app) {
    */
   /* eslint-disable no-else-return */
   actions.deletedPageListShowWrapper = function(req, res) {
-    const behaviorType = Config.behaviorType(config);
+    const behaviorType = configManager.getConfig('crowi', 'customize:behavior');
 
-    if (!behaviorType || behaviorType === 'crowi') {
+    if (behaviorType === 'crowi') {
       // Crowi behavior for '/trash/*'
       return actions.deletedPageListShow(req, res);
     }

+ 4 - 0
src/server/service/app.js

@@ -10,6 +10,10 @@ class AppService {
     this.configManager = configManager;
   }
 
+  getAppTitle() {
+    return this.configManager.getConfig('crowi', 'app:title') || 'GROWI';
+  }
+
   /**
    * get the site url
    *

+ 56 - 0
src/server/service/customize.js

@@ -0,0 +1,56 @@
+const logger = require('@alias/logger')('growi:service:CustomizeService'); // eslint-disable-line no-unused-vars
+
+/**
+ * the service class of CustomizeService
+ */
+class CustomizeService {
+
+  constructor(configManager, appService, xssService) {
+    this.configManager = configManager;
+    this.appService = appService;
+    this.xssService = xssService;
+  }
+
+  /**
+   * initialize custom css strings
+   */
+  initCustomCss() {
+    const uglifycss = require('uglifycss');
+
+    const rawCss = this.configManager.getConfig('crowi', 'customize:css') || '';
+
+    // uglify and store
+    this.customCss = uglifycss.processString(rawCss);
+  }
+
+  getCustomCss() {
+    return this.customCss;
+  }
+
+  getCustomScript() {
+    return this.configManager.getConfig('crowi', 'customize:script') || '';
+  }
+
+  initCustomTitle() {
+    let configValue = this.configManager.getConfig('crowi', 'customize:title');
+
+    if (configValue == null || configValue.trim().length === 0) {
+      configValue = '{{page}} - {{sitename}}';
+    }
+
+    this.customTitleTemplate = configValue;
+  }
+
+  generateCustomTitle(page) {
+    // replace
+    const customTitle = this.customTitleTemplate
+      .replace('{{sitename}}', this.appService.getAppTitle())
+      .replace('{{page}}', page);
+
+    return this.xssService.process(customTitle);
+  }
+
+
+}
+
+module.exports = CustomizeService;

+ 8 - 0
src/server/service/xss.js

@@ -1,4 +1,6 @@
 const logger = require('@alias/logger')('growi:service:XssSerivce'); // eslint-disable-line no-unused-vars
+
+const Xss = require('@commons/service/xss');
 const { tags, attrs } = require('@commons/service/xss/recommended-whitelist');
 
 /**
@@ -8,6 +10,12 @@ class XssSerivce {
 
   constructor(configManager) {
     this.configManager = configManager;
+
+    this.xss = new Xss();
+  }
+
+  process(value) {
+    return this.xss.process(value);
   }
 
   getTagWhiteList() {

+ 19 - 38
src/server/util/swigFunctions.js

@@ -42,22 +42,17 @@ module.exports = function(crowi, app, req, locals) {
   /**
    * @see ConfigManager#getConfig
    */
-  locals.getConfig = function(namespace, key) {
-    return crowi.configManager.getConfig(namespace, key);
-  };
+  locals.getConfig = configManager.getConfig.bind(configManager);
 
   /**
    * **Do not use this unless absolutely necessary. Use getConfig instead.**
    */
-  locals.getConfigFromDB = function(namespace, key) {
-    return crowi.configManager.getConfigFromDB(namespace, key);
-  };
+  locals.getConfigFromDB = configManager.getConfigFromDB.bind(configManager);
+
   /**
    * **Do not use this unless absolutely necessary. Use getConfig instead.**
    */
-  locals.getConfigFromEnvVars = function(namespace, key) {
-    return crowi.configManager.getConfigFromEnvVars(namespace, key);
-  };
+  locals.getConfigFromEnvVars = configManager.getConfigFromEnvVars.bind(configManager);
 
   /**
    * return app title
@@ -174,10 +169,6 @@ module.exports = function(crowi, app, req, locals) {
     return Config.isEnabledLinebreaksInComments(config);
   };
 
-  locals.customCss = function() {
-    return Config.customCss();
-  };
-
   locals.pageBreakSeparator = function() {
     const config = crowi.getConfig();
     return Config.pageBreakSeparator(config);
@@ -188,48 +179,43 @@ module.exports = function(crowi, app, req, locals) {
     return Config.pageBreakCustomSeparator(config);
   };
 
-  locals.customScript = function() {
-    return Config.customScript();
+  locals.customCss = function() {
+    const customizeService = crowi.customizeService;
+    return customizeService.getCustomCss();
   };
 
-  locals.customHeader = function() {
-    const config = crowi.getConfig();
-    return Config.customHeader(config);
+  locals.customScript = function() {
+    const customizeService = crowi.customizeService;
+    return customizeService.getCustomScript();
   };
 
-  locals.theme = function() {
-    const config = crowi.getConfig();
-    return Config.theme(config);
+  locals.customHeader = function() {
+    return configManager.getConfig('crowi', 'customize:header') || '';
   };
 
   locals.customTitle = function(page) {
-    const config = crowi.getConfig();
-    return Config.customTitle(config, page);
+    const customizeService = crowi.customizeService;
+    return customizeService.generateCustomTitle(page);
   };
 
   locals.behaviorType = function() {
-    const config = crowi.getConfig();
-    return Config.behaviorType(config);
+    return configManager.getConfig('crowi', 'customize:behavior');
   };
 
   locals.layoutType = function() {
-    const config = crowi.getConfig();
-    return Config.layoutType(config);
+    return configManager.getConfig('crowi', 'customize:layout');
   };
 
   locals.highlightJsStyle = function() {
-    const config = crowi.getConfig();
-    return Config.highlightJsStyle(config);
+    return configManager.getConfig('crowi', 'customize:highlightJsStyle');
   };
 
   locals.highlightJsStyleBorder = function() {
-    const config = crowi.getConfig();
-    return Config.highlightJsStyleBorder(config);
+    return configManager.getConfig('crowi', 'customize:highlightJsStyleBorder');
   };
 
   locals.isEnabledTimeline = function() {
-    const config = crowi.getConfig();
-    return Config.isEnabledTimeline(config);
+    return configManager.getConfig('crowi', 'customize:isEnabledTimeline');
   };
 
   locals.isUploadable = function() {
@@ -237,11 +223,6 @@ module.exports = function(crowi, app, req, locals) {
     return Config.isUploadable(config);
   };
 
-  locals.isEnabledAttachTitleHeader = function() {
-    const config = crowi.getConfig();
-    return Config.isEnabledAttachTitleHeader(config);
-  };
-
   locals.parentPath = function(path) {
     if (path === '/') {
       return path;

+ 4 - 11
src/server/views/admin/customize.html

@@ -3,18 +3,11 @@
 {% block html_title %}{{ customTitle(t('Customize')) }} {% endblock %}
 
 {% block theme_css_block %}
-  {% if 'kibela' === layoutType() %}
-    {% if env === 'development' %}
-      <script src="{{ webpack_asset('styles/theme-kibela.js') }}"></script>
-    {% else %}
-      <link rel="stylesheet" href="{{ webpack_asset('styles/theme-kibela.css') }}">
-    {% endif %}
+  {% set themeName = getConfig('crowi', 'customize:theme') %}
+  {% if env === 'development' %}
+    <script src="{{ webpack_asset('styles/theme-' + themeName + '.js') }}"></script>
   {% else %}
-    {% if env === 'development' %}
-      <script src="{{ webpack_asset('styles/theme-' + theme() + '.js') }}"></script>
-    {% else %}
-    <link rel="stylesheet" id="jssDefault" {# append id for theme selector #} href="{{ webpack_asset('styles/theme-' + theme() + '.css') }}">
-    {% endif %}
+  <link rel="stylesheet" id="jssDefault" {# append id for theme selector #} href="{{ webpack_asset('styles/theme-' + themeName + '.css') }}">
   {% endif %}
 {% endblock %}
 

+ 75 - 41
src/server/views/installer.html

@@ -1,59 +1,93 @@
-{% extends 'layout/layout.html' %}
+<!DOCTYPE html>
+<html>
+{% block html_head %}
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <title>{{ customTitle(t('installer.setup')) }}</title>
+  <meta name="description" content="">
+  <meta name="author" content="">
 
-{% block html_base_css %}installer nologin{% endblock %}
+  <meta name="viewport" content="width=device-width,initial-scale=1">
 
-{% block html_title %}{{ customTitle(t('installer.setup')) }}{% endblock %}
+  <meta name="apple-mobile-web-app-title" content="{{ appTitle() }}">
 
-{#
- # Remove default contents
- #}
-{% block html_head_loading_legacy %}
-{% endblock %}
-{% block html_head_loading_app %}
-{% endblock %}
-{% block layout_head_nav %}
-{% endblock %}
-{% block sidebar %}
-{% endblock %}
+  {% include './widget/headers/favicon.html' %}
+  {% include './widget/headers/ie11-polyfills.html' %}
+
+  {{ cdnScriptTagsByGroup('basis') }}
+
+  {% include './widget/headers/scripts-for-dev.html' %}
+
+  <script src="{{ webpack_asset('js/vendors.js') }}" defer></script>
+  <script src="{{ webpack_asset('js/commons.js') }}" defer></script>
+
+  <!-- styles -->
+  {% include './widget/headers/styles-for-app.html' %}
+  {% block theme_css_block %}
+    {% include './widget/headers/styles-theme.html' with {theme: 'default'} %}
+  {% endblock %}
+
+  {{ cdnStyleTagsByGroup('basis') }}
 
-{% block html_additional_headers %}
-  {% parent %}
   <script src="{{ webpack_asset('js/installer.js') }}" defer></script>
+
+</head>
 {% endblock %}
 
-{% block layout_main %}
+{% block html_body %}
+<body
+  class="main-container content-wrapper installer nologin growi"
+  {% block html_base_attr %}{% endblock %}
+  data-csrftoken="{{ csrf() }}"
+ >
+
+<div id="wrapper">
 
-<div class="main container-fluid">
+  <!-- Page Content -->
+  <div id="page-wrapper">
+    <div class="main container-fluid">
 
-  <div class="row">
+      <div class="row">
 
-    <div class="login-header col-sm-offset-4 col-sm-4">
-      <div class="logo">{% include 'widget/logo.html' %}</div>
-      <h1>GROWI</h1>
+        <div class="login-header col-sm-offset-4 col-sm-4">
+          <div class="logo">{% include 'widget/logo.html' %}</div>
+          <h1>GROWI</h1>
 
-      <div class="login-form-errors">
-        {% if req.form.errors.length > 0 %}
-        <div class="alert alert-danger">
-          <ul>
-          {% for error in req.form.errors %}
-            <li>{{ error }}</li>
-          {% endfor %}
-          </ul>
+          <div class="login-form-errors">
+            {% if req.form.errors.length > 0 %}
+            <div class="alert alert-danger">
+              <ul>
+              {% for error in req.form.errors %}
+                <li>{{ error }}</li>
+              {% endfor %}
+              </ul>
+            </div>
+            {% endif %}
+          </div>
         </div>
-        {% endif %}
-      </div>
-    </div>
 
-    <div id='installer-form'
-      data-user-name="{{ req.body.registerForm.username }}"
-      data-name="{{ googleName|default(req.body.registerForm.name) }}"
-      data-email="{{ googleEmail|default(req.body.registerForm.email) }}"
-      data-csrf="{{ csrf() }}">
-    </div>
+        <div id='installer-form'
+          data-user-name="{{ req.body.registerForm.username }}"
+          data-name="{{ googleName|default(req.body.registerForm.name) }}"
+          data-email="{{ googleEmail|default(req.body.registerForm.email) }}"
+          data-csrf="{{ csrf() }}">
+        </div>
 
-  </div>{# /.row #}
+      </div>{# /.row #}
 
-</div>{# /.main #}
+    </div>
+  </div><!-- /#page-wrapper -->
+
+</div><!-- /#wrapper -->
 
+{% block body_end %}
 {% endblock %}
+</body>
+{% endblock %}
+
+<script type="application/json" id="crowi-context-hydrate">
+{{ local_config|json|safe|preventXss }}
+</script>
 
+</html>

+ 15 - 62
src/server/views/layout/layout.html

@@ -12,50 +12,18 @@
 
   <meta name="apple-mobile-web-app-title" content="{{ appTitle() }}">
 
-  {% include '../widget/favicon.html' %}
-
   {{ customHeader() }}
 
-  <!-- polyfills for IE11 -->
-  <script>
-    var userAgent = window.navigator.userAgent.toLowerCase();
-    if (userAgent.indexOf('msie') != -1 || userAgent.indexOf('trident') != -1) {
-      var scriptElement = document.createElement('script');
-      scriptElement.src = '{{ webpack_asset("js/ie11-polyfill.js") }}';
-      var headElement = document.getElementsByTagName('head')[0];
-      headElement.appendChild(scriptElement);
-    }
-  </script>
+  {% include '../widget/headers/favicon.html' %}
+  {% include '../widget/headers/ie11-polyfills.html' %}
 
   {{ cdnScriptTagsByGroup('basis') }}
 
   {% if local_config.env.MATHJAX %}
-    <!-- Mathjax -->
-    <script type="text/x-mathjax-config" async>
-      MathJax.Hub.Config({
-        skipStartupTypeset: true,
-        extensions: ["tex2jax.js"],
-        jax: ["input/TeX", "output/SVG"],
-        tex2jax: {
-          processEscapes: true
-        },
-        showMathMenu: false,
-        showMathMenuMSIE: false,
-        showProcessingMessages: false,
-        messageStyle: "none"
-      });
-    </script>
-    {{ cdnScriptTag('mathjax') }}
+    {% include '../widget/headers/mathjax.html' %}
   {% endif %}
 
-  {% if env === 'development' %}
-    <script src="/dll/dll.js"></script>
-    <script src="{{ webpack_asset('js/dev.js') }}" async></script>
-    <!-- Browsersync -->
-    <script id="__bs_script__">//<![CDATA[
-      document.write("<script async src='http://HOST:3001/browser-sync/browser-sync-client.js?v=2.23.6'><\/script>".replace("HOST", location.hostname));
-    //]]></script>
-  {% endif %}
+  {% include '../widget/headers/scripts-for-dev.html' %}
 
   <script src="{{ webpack_asset('js/vendors.js') }}" defer></script>
   <script src="{{ webpack_asset('js/commons.js') }}" defer></script>
@@ -63,37 +31,22 @@
   <script src="{{ webpack_asset('js/plugin.js') }}" defer></script>
   {% endif %}
   {% block html_head_loading_legacy %}
-  <script src="{{ webpack_asset('js/legacy.js') }}" defer></script>
+    <script src="{{ webpack_asset('js/legacy.js') }}" defer></script>
   {% endblock %}
   {% block html_head_loading_app %}
-  <script src="{{ webpack_asset('js/app.js') }}" defer></script>
+    <script src="{{ webpack_asset('js/app.js') }}" defer></script>
   {% endblock %}
 
   <!-- styles -->
-  {% block style_css_block %}
-    {% if env === 'development' %}
-      <script src="{{ webpack_asset('styles/style-commons.js') }}"></script>
-      <script src="{{ webpack_asset('styles/style-app.js') }}"></script>
-    {% else %}
-      <script src="{{ webpack_asset('styles/style-commons.js') }}"></script>
-      <link rel="stylesheet" href="{{ webpack_asset('styles/style-app.css') }}">
-    {% endif %}
-  {% endblock %}
-  {% block theme_css_block %}
-    {% if 'kibela' === layoutType() %}
-      {% if env === 'development' %}
-        <script src="{{ webpack_asset('styles/theme-kibela.js') }}"></script>
-      {% else %}
-        <link rel="stylesheet" href="{{ webpack_asset('styles/theme-kibela.css') }}">
-      {% endif %}
-    {% else %}
-      {% if env === 'development' %}
-        <script src="{{ webpack_asset('styles/theme-' + theme() + '.js') }}"></script>
-      {% else %}
-        <link rel="stylesheet" href="{{ webpack_asset('styles/theme-' + theme() + '.css') }}">
-      {% endif %}
-    {% endif %}
-  {% endblock %}
+  {% include '../widget/headers/styles-for-app.html' %}
+  {% if 'kibela' === getConfig('crowi', 'customize:layout') %}
+    {% include '../widget/headers/styles-theme-kibela.html' %}
+  {% else %}
+    {% block theme_css_block %}
+      {% set themeName = getConfig('crowi', 'customize:theme') %}
+      {% include '../widget/headers/styles-theme.html' with {themeName: themeName} %}
+    {% endblock %}
+  {% endif %}
 
   {{ cdnStyleTagsByGroup('basis') }}
   {{ cdnHighlightJsStyleTag(highlightJsStyle()) }}

+ 0 - 0
src/server/views/widget/favicon.html → src/server/views/widget/headers/favicon.html


+ 10 - 0
src/server/views/widget/headers/ie11-polyfills.html

@@ -0,0 +1,10 @@
+<!-- polyfills for IE11 -->
+<script>
+  var userAgent = window.navigator.userAgent.toLowerCase();
+  if (userAgent.indexOf('msie') != -1 || userAgent.indexOf('trident') != -1) {
+    var scriptElement = document.createElement('script');
+    scriptElement.src = '{{ webpack_asset("js/ie11-polyfill.js") }}';
+    var headElement = document.getElementsByTagName('head')[0];
+    headElement.appendChild(scriptElement);
+  }
+</script>

+ 16 - 0
src/server/views/widget/headers/mathjax.html

@@ -0,0 +1,16 @@
+<!-- Mathjax -->
+<script type="text/x-mathjax-config" async>
+  MathJax.Hub.Config({
+    skipStartupTypeset: true,
+    extensions: ["tex2jax.js"],
+    jax: ["input/TeX", "output/SVG"],
+    tex2jax: {
+      processEscapes: true
+    },
+    showMathMenu: false,
+    showMathMenuMSIE: false,
+    showProcessingMessages: false,
+    messageStyle: "none"
+  });
+</script>
+{{ cdnScriptTag('mathjax') }}

+ 8 - 0
src/server/views/widget/headers/scripts-for-dev.html

@@ -0,0 +1,8 @@
+{% if env === 'development' %}
+  <script src="/dll/dll.js"></script>
+  <script src="{{ webpack_asset('js/dev.js') }}" async></script>
+  <!-- Browsersync -->
+  <script id="__bs_script__">//<![CDATA[
+    document.write("<script async src='http://HOST:3001/browser-sync/browser-sync-client.js?v=2.23.6'><\/script>".replace("HOST", location.hostname));
+  //]]></script>
+{% endif %}

+ 7 - 0
src/server/views/widget/headers/styles-for-app.html

@@ -0,0 +1,7 @@
+{% if env === 'development' %}
+  <script src="{{ webpack_asset('styles/style-commons.js') }}"></script>
+  <script src="{{ webpack_asset('styles/style-app.js') }}"></script>
+{% else %}
+  <script src="{{ webpack_asset('styles/style-commons.js') }}"></script>
+  <link rel="stylesheet" href="{{ webpack_asset('styles/style-app.css') }}">
+{% endif %}

+ 5 - 0
src/server/views/widget/headers/styles-theme-kibela.html

@@ -0,0 +1,5 @@
+{% if env === 'development' %}
+  <script src="{{ webpack_asset('styles/theme-kibela.js') }}"></script>
+{% else %}
+  <link rel="stylesheet" href="{{ webpack_asset('styles/theme-kibela.css') }}">
+{% endif %}

+ 5 - 0
src/server/views/widget/headers/styles-theme.html

@@ -0,0 +1,5 @@
+{% if env === 'development' %}
+  <script src="{{ webpack_asset('styles/theme-' + themeName + '.js') }}"></script>
+{% else %}
+  <link rel="stylesheet" href="{{ webpack_asset('styles/theme-' + themeName + '.css') }}">
+{% endif %}

+ 1 - 1
src/server/views/widget/not_found_content.html

@@ -18,7 +18,7 @@
   {% include 'not_found_tabs.html' %}
 
   <div class="tab-content">
-    {% if isEnabledAttachTitleHeader() %}
+    {% if getConfig('crowi', 'customize:isEnabledAttachTitleHeader') %}
     {% if template %}
     <script type="text/template" id="raw-text-original"># {{ path|path2name }}&NewLine;{{ template }}</script>
     {% else %}