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

Merge branch 'imprv/update-cache-bulk' into imprv/update-cache-bulk-with-comments

yusuketk пре 5 година
родитељ
комит
bbc3c57df5
100 измењених фајлова са 1025 додато и 836 уклоњено
  1. 4 1
      resource/locales/en-US/admin/admin.json
  2. 132 43
      resource/locales/en-US/sandbox-bootstrap4.md
  3. 5 5
      resource/locales/en-US/sandbox.md
  4. 4 6
      resource/locales/en-US/welcome.md
  5. 4 1
      resource/locales/ja/admin/admin.json
  6. 132 43
      resource/locales/ja/sandbox-bootstrap4.md
  7. 5 5
      resource/locales/ja/sandbox.md
  8. 1 1
      resource/locales/ja/translation.json
  9. 5 7
      resource/locales/ja/welcome.md
  10. 0 2
      src/client/js/app.jsx
  11. 2 0
      src/client/js/bootstrap.jsx
  12. 16 6
      src/client/js/components/Admin/Customize/CustomizeTitle.jsx
  13. 1 1
      src/client/js/components/Admin/ExportArchiveData/ArchiveFilesTable.jsx
  14. 7 11
      src/client/js/components/Admin/ExportArchiveData/ArchiveFilesTableMenu.jsx
  15. 1 1
      src/client/js/components/Admin/ImportData/GrowiArchive/ImportCollectionItem.jsx
  16. 2 2
      src/client/js/components/Admin/MarkdownSetting/XssForm.jsx
  17. 2 2
      src/client/js/components/Admin/Notification/GlobalNotificationList.jsx
  18. 3 3
      src/client/js/components/Admin/Notification/ManageGlobalNotification.jsx
  19. 1 1
      src/client/js/components/Admin/Security/SecurityManagement.jsx
  20. 4 3
      src/client/js/components/Admin/UserManagement.jsx
  21. 3 5
      src/client/js/components/Admin/Users/ExternalAccountTable.jsx
  22. 1 1
      src/client/js/components/Admin/Users/RemoveAdminButton.jsx
  23. 1 1
      src/client/js/components/Admin/Users/StatusActivateButton.jsx
  24. 1 1
      src/client/js/components/Admin/Users/StatusSuspendedButton.jsx
  25. 1 1
      src/client/js/components/Admin/Users/UserRemoveButton.jsx
  26. 3 7
      src/client/js/components/CreateTemplateModal.jsx
  27. 17 17
      src/client/js/components/LoginForm.jsx
  28. 1 1
      src/client/js/components/Me/PasswordSettings.jsx
  29. 30 32
      src/client/js/components/Me/PersonalSettings.jsx
  30. 0 5
      src/client/js/components/Navbar/PersonalDropdown.jsx
  31. 6 8
      src/client/js/components/PageCreateModal.jsx
  32. 1 1
      src/client/js/components/PageDeleteModal.jsx
  33. 13 16
      src/client/js/components/PageEditor/CodeMirrorEditor.jsx
  34. 1 1
      src/client/js/components/PageEditor/OptionsSelector.jsx
  35. 9 7
      src/client/js/components/PageHistory/Revision.jsx
  36. 1 1
      src/client/js/components/RecentCreated/RecentCreated.jsx
  37. 15 9
      src/client/js/components/SavePageControls/GrantSelector.jsx
  38. 13 8
      src/client/js/components/Sidebar/SidebarNav.jsx
  39. 1 1
      src/client/js/components/User/UserPictureList.jsx
  40. 17 5
      src/client/js/services/PageContainer.js
  41. 0 78
      src/client/styles/agile-admin/inverse/variables.scss
  42. 0 1
      src/client/styles/scss/_editor-attachment.scss
  43. 2 1
      src/client/styles/scss/_hljs.scss
  44. 1 24
      src/client/styles/scss/_layout.scss
  45. 1 2
      src/client/styles/scss/_layout_growi.scss
  46. 0 8
      src/client/styles/scss/_layout_variable.scss
  47. 0 2
      src/client/styles/scss/_mixins.scss
  48. 0 1
      src/client/styles/scss/_on-edit.scss
  49. 13 27
      src/client/styles/scss/_override-bootstrap-variables.scss
  50. 0 9
      src/client/styles/scss/_override-bootstrap.scss
  51. 1 9
      src/client/styles/scss/_search.scss
  52. 13 0
      src/client/styles/scss/_vendor-presentation.scss
  53. 1 12
      src/client/styles/scss/_wiki.scss
  54. 11 0
      src/client/styles/scss/atoms/_code.scss
  55. 4 0
      src/client/styles/scss/atoms/_pre.scss
  56. 2 2
      src/client/styles/scss/style-app.scss
  57. 4 7
      src/client/styles/scss/style-presentation.scss
  58. 21 59
      src/client/styles/scss/theme/_apply-colors-dark.scss
  59. 5 0
      src/client/styles/scss/theme/_apply-colors-kibela.scss
  60. 14 0
      src/client/styles/scss/theme/_apply-colors-light.scss
  61. 35 9
      src/client/styles/scss/theme/_apply-colors.scss
  62. 0 34
      src/client/styles/scss/theme/_mixins-for-tables.scss
  63. 0 2
      src/client/styles/scss/theme/_reboot-bootstrap-colors.scss
  64. 41 0
      src/client/styles/scss/theme/_reboot-bootstrap-nav.scss
  65. 72 0
      src/client/styles/scss/theme/_reboot-bootstrap-tables.scss
  66. 10 4
      src/client/styles/scss/theme/_reboot-bootstrap-theme-colors.scss
  67. 28 11
      src/client/styles/scss/theme/antarctic.scss
  68. 30 54
      src/client/styles/scss/theme/christmas.scss
  69. 34 6
      src/client/styles/scss/theme/default.scss
  70. 35 47
      src/client/styles/scss/theme/future.scss
  71. 35 32
      src/client/styles/scss/theme/halloween.scss
  72. 3 0
      src/client/styles/scss/theme/island.scss
  73. 16 67
      src/client/styles/scss/theme/kibela.scss
  74. 34 0
      src/client/styles/scss/theme/mixins/_tables.scss
  75. 6 3
      src/client/styles/scss/theme/mono-blue.scss
  76. 7 6
      src/client/styles/scss/theme/nature.scss
  77. 21 12
      src/client/styles/scss/theme/spring.scss
  78. 4 3
      src/client/styles/scss/theme/wood.scss
  79. 4 2
      src/lib/models/devided-page-path.js
  80. 6 4
      src/lib/models/linked-page-path.js
  81. 2 2
      src/server/models/user.js
  82. 1 3
      src/server/routes/apiv3/users.js
  83. 1 1
      src/server/routes/installer.js
  84. 22 4
      src/server/service/customize.js
  85. 1 1
      src/server/service/passport.js
  86. 1 1
      src/server/views/admin/app.html
  87. 4 1
      src/server/views/admin/customize.html
  88. 1 1
      src/server/views/admin/export.html
  89. 1 1
      src/server/views/admin/external-accounts.html
  90. 1 1
      src/server/views/admin/global-notification-detail.html
  91. 1 1
      src/server/views/admin/importer.html
  92. 1 1
      src/server/views/admin/index.html
  93. 1 1
      src/server/views/admin/markdown.html
  94. 1 1
      src/server/views/admin/notification.html
  95. 1 1
      src/server/views/admin/search.html
  96. 1 1
      src/server/views/admin/security.html
  97. 1 1
      src/server/views/admin/user-group-detail.html
  98. 1 1
      src/server/views/admin/user-groups.html
  99. 1 1
      src/server/views/admin/users.html
  100. 1 1
      src/server/views/installer.html

+ 4 - 1
resource/locales/en-US/admin/admin.json

@@ -125,7 +125,10 @@
     "code_highlight": "Code highlight",
     "code_highlight": "Code highlight",
     "nocdn_desc": "This function is disabled when the environment variable <code>NO_CDN=true</code>.<br>Github style has been forcibly applied.",
     "nocdn_desc": "This function is disabled when the environment variable <code>NO_CDN=true</code>.<br>Github style has been forcibly applied.",
     "custom_title": "Custom title",
     "custom_title": "Custom title",
-    "custom_title_detail": "You can customize <code>&lt;title&gt;</code> tag.<br><code>&#123;&#123;sitename&#125;&#125;</code> will be automatically replaced with the app name, and <code>&#123;&#123;page&#125;&#125;</code> will be replaced with the page name/path.",
+    "custom_title_detail": "You can customize <code>&lt;title&gt;</code> tag. Following placeholders will be automatically replaced:",
+    "custom_title_detail_placeholder1": "<code>&#123;&#123;sitename&#125;&#125;</code> - The site name of this wiki.",
+    "custom_title_detail_placeholder2": "<code>&#123;&#123;pagename&#125;&#125;</code> - The page name of the current page.",
+    "custom_title_detail_placeholder3": "<code>&#123;&#123;pagepath&#125;&#125;</code> - The page path of the current page.",
     "custom_header": "Custom HTML header",
     "custom_header": "Custom HTML header",
     "custom_header_detail": "You can customize HTML header that applies all pages. Your custom script will be inserted in <code>&lt;header&gt;</code> but above other <code>&lt;script&gt;</code> tags.<br>Relaod page to see changes.",
     "custom_header_detail": "You can customize HTML header that applies all pages. Your custom script will be inserted in <code>&lt;header&gt;</code> but above other <code>&lt;script&gt;</code> tags.<br>Relaod page to see changes.",
     "custom_css": "Custom CSS",
     "custom_css": "Custom CSS",

+ 132 - 43
resource/locales/en-US/sandbox-bootstrap4.md

@@ -6,92 +6,181 @@
 <span class="badge badge-info">Info</span>
 <span class="badge badge-info">Info</span>
 <span class="badge badge-warning">Warning</span>
 <span class="badge badge-warning">Warning</span>
 <span class="badge badge-danger">Danger</span>
 <span class="badge badge-danger">Danger</span>
-<span class="badge badge-light">Light</span>
+<span class="badge badge-light text-dark">Light</span>
 <span class="badge badge-dark">Dark</span>
 <span class="badge badge-dark">Dark</span>
 
 
+<span class="badge badge-blue">Blue</span>
+<span class="badge badge-indigo">Indigo</span>
+<span class="badge badge-purple">Purple</span>
+<span class="badge badge-pink">Pink</span>
+<span class="badge badge-red">Red</span>
+<span class="badge badge-orange">Orange</span>
+<span class="badge badge-yellow">Yellow</span>
+<span class="badge badge-green">Green</span>
+<span class="badge badge-teal">Teal</span>
+<span class="badge badge-cyan">Cyan</span>
+
+
 # Alerts
 # Alerts
 
 
-<div class="alert alert-success" role="alert"><b>Well done!</b> You successfully read this important alert message. </div>
-<div class="alert alert-info" role="alert"><b>Heads up!</b> This alert needs your attention, but it's not super important. </div>
-<div class="alert alert-warning" role="alert"><b>Warning!</b> Better check yourself, you're not looking too good. </div>
-<div class="alert alert-danger" role="alert"><b>Oh snap!</b> Change a few things up and try submitting again. </div>
+<div class="alert alert-primary" role="alert">
+  This is a primary alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-secondary" role="alert">
+  This is a secondary alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-success" role="alert">
+  This is a success alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-danger" role="alert">
+  This is a danger alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-warning" role="alert">
+  This is a warning alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-info" role="alert">
+  This is a info alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-light text-dark" role="alert">
+  This is a light alert with <a href="#" class="alert-link text-dark">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-dark" role="alert">
+  This is a dark alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
 
 
 # Cards
 # Cards
 
 
-<div class="card">
-  <div class="card-header">Card header without title</div>
+<div class="d-flex">
+
+<div class="mr-3">
+<div class="card text-white bg-primary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Primary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-light">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-secondary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Secondary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-secondary text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-success mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Success card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-dark text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-danger mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Danger card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-primary text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-warning mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Warning card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-success text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-info mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Info card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-info text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card bg-light mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Light card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-warning text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-dark mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Dark card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
+</div>
 
 
-<div class="card bg-danger text-white">
-  <div class="card-header">Card header without title</div>
+<div>
+<div class="card border-primary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-primary">
+    <h5 class="card-title">Primary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-secondary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-secondary">
+    <h5 class="card-title">Secondary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-success mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-success">
+    <h5 class="card-title">Success card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-danger mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-danger">
+    <h5 class="card-title">Danger card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-warning mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-warning">
+    <h5 class="card-title">Warning card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-info mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-info">
+    <h5 class="card-title">Info card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-light mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Light card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-dark mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-dark">
+    <h5 class="card-title">Dark card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
+</div>
+
+</div>
 
 
 # Wells
 # Wells
 
 
 ## Default well
 ## Default well
 
 
-<div class="card card-body bg-light">Look, I'm in a well! </div>
+<div class="card card-body">Look, I'm in a well! </div>
 
 
 ## Optional classes
 ## Optional classes
 
 
-<div class="card card-body bg-light p-5">Look, I'm in a well! </div>
-
-<div class="card card-body bg-light p-2">Look, I'm in a well! </div>
+<div class="card card-body bg-primary text-light p-2">Look, I'm in a well! </div>
 
 
 # Typography
 # Typography
 
 

+ 5 - 5
resource/locales/en-US/sandbox.md

@@ -252,12 +252,12 @@ This is the most flexible linker.
 Both the page description and link address can be displayed on the page.
 Both the page description and link address can be displayed on the page.
 
 
 ```
 ```
-[[./Bootstrap3]]
-Example of Bootstrap3 is[[here>./Bootstrap3]]
+[[./Bootstrap4]]
+Example of Bootstrap4 is[[here>./Bootstrap4]]
 ```
 ```
 
 
 [[../user]]
 [[../user]]
-Example of Bootstrap3 is[[here>./Bootstrap3]]
+Example of Bootstrap4 is[[here>./Bootstrap4]]
 
 
 # :pencil: Lists
 # :pencil: Lists
 
 
@@ -449,8 +449,8 @@ See [emojione](https://www.emojione.com/)
 
 
 # :heavy_plus_sign: More..
 # :heavy_plus_sign: More..
 
 
-- Try to attach Bootstrap3 Tags?
-    - :arrow_right: [/Sandbox/Bootstrap3]
+- Try to attach Bootstrap4 Tags?
+    - :arrow_right: [/Sandbox/Bootstrap4]
 - Try to draw Diagrams?
 - Try to draw Diagrams?
     - :arrow_right: [/Sandbox/Diagrams]
     - :arrow_right: [/Sandbox/Diagrams]
 - Try to write Math Formulas?
 - Try to write Math Formulas?

+ 4 - 6
resource/locales/en-US/welcome.md

@@ -3,16 +3,14 @@
 [![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest)
 [![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest)
 [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
 [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
 
 
-<div class="card">
-  <div class="card-header">Tips</div>
+<div class="card border-primary">
+  <div class="card-header bg-primary text-light">Tips</div>
   <div class="card-body"><ul>
   <div class="card-body"><ul>
-    <li>Ctrl(⌘)-/ to show quick help</li>
-    <li>You can write HTML with <a href="https://getbootstrap.com/docs/3.3/css/">Bootstrap 3</a>.</li>
+    <li>Ctrl(⌘) + "/" to show quick help</li>
+    <li>You can write HTML with <a href="https://getbootstrap.com/docs/4.5/components/">Bootstrap 4</a>.</li>
   </ul></div>
   </ul></div>
 </div>
 </div>
 
 
-<div class="clearfix"></div>
-
 Contents
 Contents
 =========
 =========
 
 

+ 4 - 1
resource/locales/ja/admin/admin.json

@@ -125,7 +125,10 @@
     "code_highlight": "コードハイライト",
     "code_highlight": "コードハイライト",
     "nocdn_desc": "この機能は、環境変数 <code>NO_CDN=true</code> の時は無効化されます。<br>GitHub スタイルが適用されています。",
     "nocdn_desc": "この機能は、環境変数 <code>NO_CDN=true</code> の時は無効化されます。<br>GitHub スタイルが適用されています。",
     "custom_title": "カスタム Title",
     "custom_title": "カスタム Title",
-    "custom_title_detail": "<code>&lt;title&gt;</code>タグのコンテンツをカスタマイズできます。<br><code>&#123;&#123;sitename&#125;&#125;</code>がサイト名、<code>&#123;&#123;page&#125;&#125;</code>がページ名またはページパスに置換されます。",
+    "custom_title_detail": "<code>&lt;title&gt;</code>タグのコンテンツをカスタマイズできます。以下のプレースホルダーは自動的に置換されます:",
+    "custom_title_detail_placeholder1": "<code>&#123;&#123;sitename&#125;&#125;</code> - この Wiki のサイト名",
+    "custom_title_detail_placeholder2": "<code>&#123;&#123;pagename&#125;&#125;</code> - 現在表示中のページ名",
+    "custom_title_detail_placeholder3": "<code>&#123;&#123;pagepath&#125;&#125;</code> - 現在表示中のページパス",
     "custom_header": "カスタム HTML Header",
     "custom_header": "カスタム HTML Header",
     "custom_header_detail": "システム全体に適用される HTML を記述できます。<code>&lt;header&gt;</code> タグ内の他の <code>&lt;script&gt;</code> タグ読み込み前に展開されます。<br>変更の反映はページの更新が必要です。",
     "custom_header_detail": "システム全体に適用される HTML を記述できます。<code>&lt;header&gt;</code> タグ内の他の <code>&lt;script&gt;</code> タグ読み込み前に展開されます。<br>変更の反映はページの更新が必要です。",
     "custom_css": "カスタム CSS",
     "custom_css": "カスタム CSS",

+ 132 - 43
resource/locales/ja/sandbox-bootstrap4.md

@@ -6,92 +6,181 @@
 <span class="badge badge-info">Info</span>
 <span class="badge badge-info">Info</span>
 <span class="badge badge-warning">Warning</span>
 <span class="badge badge-warning">Warning</span>
 <span class="badge badge-danger">Danger</span>
 <span class="badge badge-danger">Danger</span>
-<span class="badge badge-light">Light</span>
+<span class="badge badge-light text-dark">Light</span>
 <span class="badge badge-dark">Dark</span>
 <span class="badge badge-dark">Dark</span>
 
 
+<span class="badge badge-blue">Blue</span>
+<span class="badge badge-indigo">Indigo</span>
+<span class="badge badge-purple">Purple</span>
+<span class="badge badge-pink">Pink</span>
+<span class="badge badge-red">Red</span>
+<span class="badge badge-orange">Orange</span>
+<span class="badge badge-yellow">Yellow</span>
+<span class="badge badge-green">Green</span>
+<span class="badge badge-teal">Teal</span>
+<span class="badge badge-cyan">Cyan</span>
+
+
 # Alerts
 # Alerts
 
 
-<div class="alert alert-success" role="alert"><b>Well done!</b> You successfully read this important alert message. </div>
-<div class="alert alert-info" role="alert"><b>Heads up!</b> This alert needs your attention, but it's not super important. </div>
-<div class="alert alert-warning" role="alert"><b>Warning!</b> Better check yourself, you're not looking too good. </div>
-<div class="alert alert-danger" role="alert"><b>Oh snap!</b> Change a few things up and try submitting again. </div>
+<div class="alert alert-primary" role="alert">
+  This is a primary alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-secondary" role="alert">
+  This is a secondary alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-success" role="alert">
+  This is a success alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-danger" role="alert">
+  This is a danger alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-warning" role="alert">
+  This is a warning alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-info" role="alert">
+  This is a info alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-light text-dark" role="alert">
+  This is a light alert with <a href="#" class="alert-link text-dark">an example link</a>. Give it a click if you like.
+</div>
+<div class="alert alert-dark" role="alert">
+  This is a dark alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
+</div>
 
 
 # Cards
 # Cards
 
 
-<div class="card">
-  <div class="card-header">Card header without title</div>
+<div class="d-flex">
+
+<div class="mr-3">
+<div class="card text-white bg-primary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Primary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-light">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-secondary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Secondary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-secondary text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-success mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Success card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-dark text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-danger mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Danger card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-primary text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-warning mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Warning card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-success text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-info mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Info card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-info text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card bg-light mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Light card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
-
-<div class="card bg-warning text-white">
-  <div class="card-header">Card header without title</div>
+<div class="card text-white bg-dark mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Dark card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
+</div>
 
 
-<div class="card bg-danger text-white">
-  <div class="card-header">Card header without title</div>
+<div>
+<div class="card border-primary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-primary">
+    <h5 class="card-title">Primary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-secondary mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-secondary">
+    <h5 class="card-title">Secondary card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-success mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-success">
+    <h5 class="card-title">Success card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-danger mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-danger">
+    <h5 class="card-title">Danger card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-warning mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-warning">
+    <h5 class="card-title">Warning card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-info mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-info">
+    <h5 class="card-title">Info card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-light mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
   <div class="card-body">
   <div class="card-body">
-    Card body content
+    <h5 class="card-title">Light card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
+  </div>
+</div>
+<div class="card border-dark mb-3" style="max-width: 18rem;">
+  <div class="card-header">Header</div>
+  <div class="card-body text-dark">
+    <h5 class="card-title">Dark card title</h5>
+    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
   </div>
   </div>
 </div>
 </div>
+</div>
+
+</div>
 
 
 # Wells
 # Wells
 
 
 ## Default well
 ## Default well
 
 
-<div class="card card-body bg-light">Look, I'm in a well! </div>
+<div class="card card-body">Look, I'm in a well! </div>
 
 
 ## Optional classes
 ## Optional classes
 
 
-<div class="card card-body bg-light p-5">Look, I'm in a well! </div>
-
-<div class="card card-body bg-light p-2">Look, I'm in a well! </div>
+<div class="card card-body bg-primary text-light p-2">Look, I'm in a well! </div>
 
 
 # Typography
 # Typography
 
 

+ 5 - 5
resource/locales/ja/sandbox.md

@@ -251,12 +251,12 @@ ___
 記述中のページを基点とした相対リンクと、表示テキストに対するリンクを同時に実現できます。
 記述中のページを基点とした相対リンクと、表示テキストに対するリンクを同時に実現できます。
 
 
 ```
 ```
-[[./Bootstrap3]]
-Bootstrap3のExampleは[[こちら>./Bootstrap3]]
+[[./Bootstrap4]]
+Bootstrap4のExampleは[[こちら>./Bootstrap4]]
 ```
 ```
 
 
 [[../user]]
 [[../user]]
-Bootstrap3のExampleは[[こちら>./Bootstrap3]]
+Bootstrap4のExampleは[[こちら>./Bootstrap4]]
 
 
 # :pencil: Lists
 # :pencil: Lists
 
 
@@ -449,8 +449,8 @@ See [emojione](https://www.emojione.com/)
 
 
 # :heavy_plus_sign: 更に…
 # :heavy_plus_sign: 更に…
 
 
-- Bootstrap3 のタグを使う
-    - :arrow_right: [/Sandbox/Bootstrap3]
+- Bootstrap4 のタグを使う
+    - :arrow_right: [/Sandbox/Bootstrap4]
 - 図表を書く
 - 図表を書く
     - :arrow_right: [/Sandbox/Diagrams]
     - :arrow_right: [/Sandbox/Diagrams]
 - 数式を書く
 - 数式を書く

+ 1 - 1
resource/locales/ja/translation.json

@@ -315,7 +315,7 @@
       "konami_code_url": "https://ja.wikipedia.org/wiki/コナミコマンド"
       "konami_code_url": "https://ja.wikipedia.org/wiki/コナミコマンド"
     },
     },
     "editor": {
     "editor": {
-      "titile": "エディターショートカット",
+      "title": "エディターショートカット",
       "Indent": "インデント",
       "Indent": "インデント",
       "Outdent": "左インデント",
       "Outdent": "左インデント",
       "Save Page": "保存",
       "Save Page": "保存",

+ 5 - 7
resource/locales/ja/welcome.md

@@ -3,16 +3,14 @@
 [![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest)
 [![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest)
 [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
 [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
 
 
-<div class="card">
-  <div class="card-header">Tips</div>
+<div class="card border-primary">
+  <div class="card-header bg-primary text-light">Tips</div>
   <div class="card-body"><ul>
   <div class="card-body"><ul>
-    <li>Ctrl(⌘)-/ でショートカットヘルプを表示します</li>
-      <li>HTML/CSS の記述時は、<a href="https://getbootstrap.com/docs/3.3/css/">Bootstrap 3</a> を利用できます</li>
+    <li>Ctrl(⌘) + "/" でショートカットヘルプを表示します</li>
+    <li>HTML/CSS の記述には、<a href="https://getbootstrap.com/docs/4.5/components/">Bootstrap 4</a> を利用できます</li>
   </ul></div>
   </ul></div>
 </div>
 </div>
 
 
-<div class="clearfix"></div>
-
 Contents
 Contents
 =========
 =========
 
 
@@ -26,4 +24,4 @@ Slack
 <a href="https://growi-slackin.weseek.co.jp/"><img src="https://growi-slackin.weseek.co.jp/badge.svg"></a>
 <a href="https://growi-slackin.weseek.co.jp/"><img src="https://growi-slackin.weseek.co.jp/badge.svg"></a>
 
 
 GROWI をより良いものにするために、是非 Slack に参加してください。  
 GROWI をより良いものにするために、是非 Slack に参加してください。  
-開発に関する議論を行っている他、導入時の質問等も受け付けています。
+開発に関する議論を行っている他、導入時の質問等も受け付けています。

+ 0 - 2
src/client/js/app.jsx

@@ -31,7 +31,6 @@ import MyDraftList from './components/MyDraftList/MyDraftList';
 import SeenUserPictureList from './components/User/SeenUserPictureList';
 import SeenUserPictureList from './components/User/SeenUserPictureList';
 import LikerPictureList from './components/User/LikerPictureList';
 import LikerPictureList from './components/User/LikerPictureList';
 import TableOfContents from './components/TableOfContents';
 import TableOfContents from './components/TableOfContents';
-import PageCreateModal from './components/PageCreateModal';
 
 
 import PersonalSettings from './components/Me/PersonalSettings';
 import PersonalSettings from './components/Me/PersonalSettings';
 import PageContainer from './services/PageContainer';
 import PageContainer from './services/PageContainer';
@@ -98,7 +97,6 @@ if (pageContainer.state.pageId != null) {
     'seen-user-list': <SeenUserPictureList />,
     'seen-user-list': <SeenUserPictureList />,
     'liker-list': <LikerPictureList />,
     'liker-list': <LikerPictureList />,
     'rename-page-name-input': <PagePathAutoComplete crowi={appContainer} initializedPath={pageContainer.state.path} />,
     'rename-page-name-input': <PagePathAutoComplete crowi={appContainer} initializedPath={pageContainer.state.path} />,
-    'page-create-modal': <PageCreateModal />,
 
 
     'user-created-list': <RecentCreated />,
     'user-created-list': <RecentCreated />,
     'user-draft-list': <MyDraftList />,
     'user-draft-list': <MyDraftList />,

+ 2 - 0
src/client/js/bootstrap.jsx

@@ -12,6 +12,7 @@ import StaffCredit from './components/StaffCredit/StaffCredit';
 import AppContainer from './services/AppContainer';
 import AppContainer from './services/AppContainer';
 import WebsocketContainer from './services/WebsocketContainer';
 import WebsocketContainer from './services/WebsocketContainer';
 import PageCreateButton from './components/Navbar/PageCreateButton';
 import PageCreateButton from './components/Navbar/PageCreateButton';
+import PageCreateModal from './components/PageCreateModal';
 
 
 const logger = loggerFactory('growi:app');
 const logger = loggerFactory('growi:app');
 
 
@@ -46,6 +47,7 @@ const componentMappings = {
 
 
   'create-page-button': <PageCreateButton />,
   'create-page-button': <PageCreateButton />,
   'create-page-button-icon': <PageCreateButton isIcon />,
   'create-page-button-icon': <PageCreateButton isIcon />,
+  'page-create-modal': <PageCreateModal />,
 
 
   'grw-sidebar-wrapper': <Sidebar />,
   'grw-sidebar-wrapper': <Sidebar />,
 
 

+ 16 - 6
src/client/js/components/Admin/Customize/CustomizeTitle.jsx

@@ -44,19 +44,29 @@ class CustomizeTitle extends React.Component {
           <div className="col-12">
           <div className="col-12">
             <Card className="card well">
             <Card className="card well">
               <CardBody className="px-0 py-2">
               <CardBody className="px-0 py-2">
-                <span
-                  // eslint-disable-next-line react/no-danger
-                  dangerouslySetInnerHTML={{ __html: t('admin:customize_setting.custom_title_detail') }}
-                />
+                {/* eslint-disable react/no-danger */}
+                <p dangerouslySetInnerHTML={{ __html: t('admin:customize_setting.custom_title_detail') }} />
+                <ul>
+                  <li>
+                    <span dangerouslySetInnerHTML={{ __html: t('admin:customize_setting.custom_title_detail_placeholder1') }} />
+                  </li>
+                  <li>
+                    <span dangerouslySetInnerHTML={{ __html: t('admin:customize_setting.custom_title_detail_placeholder2') }} />
+                  </li>
+                  <li>
+                    <span dangerouslySetInnerHTML={{ __html: t('admin:customize_setting.custom_title_detail_placeholder3') }} />
+                  </li>
+                </ul>
+                {/* eslint-enable react/no-danger */}
               </CardBody>
               </CardBody>
             </Card>
             </Card>
           </div>
           </div>
 
 
           {/* TODO i18n */}
           {/* TODO i18n */}
           <div className="form-text text-muted col-12">
           <div className="form-text text-muted col-12">
-            Default Value: <code>&#123;&#123;page&#125;&#125; - &#123;&#123;sitename&#125;&#125;</code>
+            Default Value: <code>&#123;&#123;pagename&#125;&#125; - &#123;&#123;sitename&#125;&#125;</code>
             <br />
             <br />
-            Default Output: <code className="xml">&lt;title&gt;/Somewhere/Page - {'GROWI'}&lt;&#047;title&gt;</code>
+            Default Output Example: <code className="xml">&lt;title&gt;Page name - My GROWI&lt;&#047;title&gt;</code>
           </div>
           </div>
           <div className="form-group col-12">
           <div className="form-group col-12">
             <input
             <input

+ 1 - 1
src/client/js/components/Admin/ExportArchiveData/ArchiveFilesTable.jsx

@@ -14,7 +14,7 @@ class ArchiveFilesTable extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <div className="table-responsive text-nowrap">
+      <div className="table-responsive">
         <table className="table table-bordered">
         <table className="table table-bordered">
           <thead>
           <thead>
             <tr>
             <tr>

+ 7 - 11
src/client/js/components/Admin/ExportArchiveData/ArchiveFilesTableMenu.jsx

@@ -12,22 +12,18 @@ class ArchiveFilesTableMenu extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <div className="btn-group admin-user-menu">
+      <div className="btn-group admin-user-menu dropdown">
         <button type="button" className="btn btn-sm btn-outline-secondary dropdown-toggle" data-toggle="dropdown">
         <button type="button" className="btn btn-sm btn-outline-secondary dropdown-toggle" data-toggle="dropdown">
           <i className="icon-settings"></i> <span className="caret"></span>
           <i className="icon-settings"></i> <span className="caret"></span>
         </button>
         </button>
         <ul className="dropdown-menu" role="menu">
         <ul className="dropdown-menu" role="menu">
           <li className="dropdown-header">{t('admin:export_management.export_menu')}</li>
           <li className="dropdown-header">{t('admin:export_management.export_menu')}</li>
-          <li>
-            <a type="button" href={`/admin/export/${this.props.fileName}`}>
-              <i className="icon-cloud-download" /> {t('admin:export_management.download')}
-            </a>
-          </li>
-          <li>
-            <a type="button" role="button" onClick={() => this.props.onZipFileStatRemove(this.props.fileName)}>
-              <span className="text-danger"><i className="icon-trash" /> {t('admin:export_management.delete')}</span>
-            </a>
-          </li>
+          <a type="button" className="dropdown-item" href={`/admin/export/${this.props.fileName}`}>
+            <i className="icon-cloud-download" /> {t('admin:export_management.download')}
+          </a>
+          <a type="button" className="dropdown-item" role="button" onClick={() => this.props.onZipFileStatRemove(this.props.fileName)}>
+            <span className="text-danger"><i className="icon-trash" /> {t('admin:export_management.delete')}</span>
+          </a>
         </ul>
         </ul>
       </div>
       </div>
     );
     );

+ 1 - 1
src/client/js/components/Admin/ImportData/GrowiArchive/ImportCollectionItem.jsx

@@ -131,7 +131,7 @@ export default class ImportCollectionItem extends React.Component {
             { modes.map((mode) => {
             { modes.map((mode) => {
               return (
               return (
                 <li key={`buttonMode_${mode}`}>
                 <li key={`buttonMode_${mode}`}>
-                  <a type="button" role="button" onClick={() => this.modeSelectedHandler(mode)}>
+                  <a type="button" className="dropdown-item" role="button" onClick={() => this.modeSelectedHandler(mode)}>
                     {this.renderModeLabel(mode, true)}
                     {this.renderModeLabel(mode, true)}
                   </a>
                   </a>
                 </li>
                 </li>

+ 2 - 2
src/client/js/components/Admin/MarkdownSetting/XssForm.jsx

@@ -75,7 +75,7 @@ class XssForm extends React.Component {
               />
               />
               <label className="custom-control-label w-100" htmlFor="xssOption2">
               <label className="custom-control-label w-100" htmlFor="xssOption2">
                 <p className="font-weight-bold">{t('admin:markdown_setting.xss_options.recommended_setting')}</p>
                 <p className="font-weight-bold">{t('admin:markdown_setting.xss_options.recommended_setting')}</p>
-                <div className="m-t-15">
+                <div className="mt-4">
                   <div className="d-flex justify-content-between">
                   <div className="d-flex justify-content-between">
                     {t('admin:markdown_setting.xss_options.tag_names')}
                     {t('admin:markdown_setting.xss_options.tag_names')}
                   </div>
                   </div>
@@ -88,7 +88,7 @@ class XssForm extends React.Component {
                     defaultValue={tags}
                     defaultValue={tags}
                   />
                   />
                 </div>
                 </div>
-                <div className="m-t-15">
+                <div className="mt-4">
                   <div className="d-flex justify-content-between">
                   <div className="d-flex justify-content-between">
                     {t('admin:markdown_setting.xss_options.tag_attributes')}
                     {t('admin:markdown_setting.xss_options.tag_attributes')}
                   </div>
                   </div>

+ 2 - 2
src/client/js/components/Admin/Notification/GlobalNotificationList.jsx

@@ -103,7 +103,7 @@ class GlobalNotificationList extends React.Component {
                   </li>
                   </li>
                 )}
                 )}
                   {notification.triggerEvents.includes('pageMove') && (
                   {notification.triggerEvents.includes('pageMove') && (
-                  <li className="list-inline-item badge badge-pill badge-warning" data-toggle="tooltip" data-placement="top" title="Page Move">
+                  <li className="list-inline-item badge badge-pill badge-pink" data-toggle="tooltip" data-placement="top" title="Page Move">
                     <i className="icon-action-redo"></i> MOVE
                     <i className="icon-action-redo"></i> MOVE
                   </li>
                   </li>
                 )}
                 )}
@@ -118,7 +118,7 @@ class GlobalNotificationList extends React.Component {
                   </li>
                   </li>
                 )}
                 )}
                   {notification.triggerEvents.includes('comment') && (
                   {notification.triggerEvents.includes('comment') && (
-                  <li className="list-inline-item badge badge-pill badge-light" data-toggle="tooltip" data-placement="top" title="New Comment">
+                  <li className="list-inline-item badge badge-pill badge-secondary" data-toggle="tooltip" data-placement="top" title="New Comment">
                     <i className="icon-fw icon-bubble"></i> POST
                     <i className="icon-fw icon-bubble"></i> POST
                   </li>
                   </li>
                 )}
                 )}

+ 3 - 3
src/client/js/components/Admin/Notification/ManageGlobalNotification.jsx

@@ -111,7 +111,7 @@ class ManageGlobalNotification extends React.Component {
 
 
 
 
         <div className="row">
         <div className="row">
-          <div className="m-t-20 form-box col-md-12">
+          <div className="form-box col-md-12">
             <h2 className="border-bottom mb-5">{t('notification_setting.notification_detail')}</h2>
             <h2 className="border-bottom mb-5">{t('notification_setting.notification_detail')}</h2>
           </div>
           </div>
 
 
@@ -242,12 +242,12 @@ class ManageGlobalNotification extends React.Component {
               </div>
               </div>
               <div className="my-1">
               <div className="my-1">
                 <TriggerEventCheckBox
                 <TriggerEventCheckBox
-                  checkbox="warning"
+                  checkbox="pink"
                   event="pageMove"
                   event="pageMove"
                   checked={this.state.triggerEvents.has('pageMove')}
                   checked={this.state.triggerEvents.has('pageMove')}
                   onChange={() => this.onChangeTriggerEvents('pageMove')}
                   onChange={() => this.onChangeTriggerEvents('pageMove')}
                 >
                 >
-                  <span className="badge badge-pill badge-warning">
+                  <span className="badge badge-pill badge-pink">
                     <i className="icon-action-redo mr-1" />MOVE
                     <i className="icon-action-redo mr-1" />MOVE
                   </span>
                   </span>
                 </TriggerEventCheckBox>
                 </TriggerEventCheckBox>

+ 1 - 1
src/client/js/components/Admin/Security/SecurityManagement.jsx

@@ -58,7 +58,7 @@ class SecurityManagement extends React.Component {
           </div>
           </div>
         </div>
         </div>
 
 
-        <div className="auth-mechanism-configurations m-t-10">
+        <div className="auth-mechanism-configurations">
           <h2 className="border-bottom">{t('security_setting.Authentication mechanism settings')}</h2>
           <h2 className="border-bottom">{t('security_setting.Authentication mechanism settings')}</h2>
           <Nav tabs>
           <Nav tabs>
             <NavItem>
             <NavItem>

+ 4 - 3
src/client/js/components/Admin/UserManagement.jsx

@@ -99,7 +99,7 @@ class UserManagement extends React.Component {
           type="checkbox"
           type="checkbox"
           id={`c_${status}`}
           id={`c_${status}`}
           checked={this.props.adminUsersContainer.isSelected(status)}
           checked={this.props.adminUsersContainer.isSelected(status)}
-          onClick={() => { this.handleClick(status) }}
+          onChange={() => { this.handleClick(status) }}
         />
         />
         <label className="custom-control-label" htmlFor={`c_${status}`}>
         <label className="custom-control-label" htmlFor={`c_${status}`}>
           <span className={`badge badge-pill badge-${statusColor} d-inline-block vt mt-1`}>
           <span className={`badge badge-pill badge-${statusColor} d-inline-block vt mt-1`}>
@@ -160,10 +160,11 @@ class UserManagement extends React.Component {
         <div className="border-top border-bottom">
         <div className="border-top border-bottom">
 
 
           <div className="row d-flex justify-content-start align-items-center my-2">
           <div className="row d-flex justify-content-start align-items-center my-2">
-            <div className="col-md-4 d-flex align-items-center my-2">
+            <div className="col-md-3 d-flex align-items-center my-2">
               <i className="icon-magnifier mr-1"></i>
               <i className="icon-magnifier mr-1"></i>
               <span className="search-typeahead">
               <span className="search-typeahead">
                 <input
                 <input
+                  className="w-100"
                   type="text"
                   type="text"
                   ref={(searchUserElement) => { this.searchUserElement = searchUserElement }}
                   ref={(searchUserElement) => { this.searchUserElement = searchUserElement }}
                   onChange={this.handleChangeSearchText}
                   onChange={this.handleChangeSearchText}
@@ -172,7 +173,7 @@ class UserManagement extends React.Component {
               </span>
               </span>
             </div>
             </div>
 
 
-            <div className="col-md-6 my-2">
+            <div className="offset-md-1 col-md-6 my-2">
               <div className="form-inline">
               <div className="form-inline">
                 {this.renderCheckbox('all', 'All', 'secondary')}
                 {this.renderCheckbox('all', 'All', 'secondary')}
                 {this.renderCheckbox('registered', 'Approval Pending', 'info')}
                 {this.renderCheckbox('registered', 'Approval Pending', 'info')}

+ 3 - 5
src/client/js/components/Admin/Users/ExternalAccountTable.jsx

@@ -99,11 +99,9 @@ class ExternalAccountTable extends React.Component {
                       </button>
                       </button>
                       <ul className="dropdown-menu" role="menu">
                       <ul className="dropdown-menu" role="menu">
                         <li className="dropdown-header">{t('admin:user_management.user_table.edit_menu')}</li>
                         <li className="dropdown-header">{t('admin:user_management.user_table.edit_menu')}</li>
-                        <li>
-                          <a role="button" onClick={() => { return this.removeExtenalAccount(ea._id) }}>
-                            <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
-                          </a>
-                        </li>
+                        <a className="dropdown-item" role="button" onClick={() => { return this.removeExtenalAccount(ea._id) }}>
+                          <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
+                        </a>
                       </ul>
                       </ul>
                     </div>
                     </div>
                   </td>
                   </td>

+ 1 - 1
src/client/js/components/Admin/Users/RemoveAdminButton.jsx

@@ -32,7 +32,7 @@ class RemoveAdminButton extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <a className="dropdown-item" href="" onClick={() => { this.onClickRemoveAdminBtn() }}>
+      <a className="dropdown-item" onClick={() => { this.onClickRemoveAdminBtn() }}>
         <i className="icon-fw icon-user-unfollow"></i> {t('admin:user_management.user_table.remove_admin_access')}
         <i className="icon-fw icon-user-unfollow"></i> {t('admin:user_management.user_table.remove_admin_access')}
       </a>
       </a>
     );
     );

+ 1 - 1
src/client/js/components/Admin/Users/StatusActivateButton.jsx

@@ -31,7 +31,7 @@ class StatusActivateButton extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <a className="dropdown-item" href="" onClick={() => { this.onClickAcceptBtn() }}>
+      <a className="dropdown-item" onClick={() => { this.onClickAcceptBtn() }}>
         <i className="icon-fw icon-user-following"></i> {t('admin:user_management.user_table.accept')}
         <i className="icon-fw icon-user-following"></i> {t('admin:user_management.user_table.accept')}
       </a>
       </a>
     );
     );

+ 1 - 1
src/client/js/components/Admin/Users/StatusSuspendedButton.jsx

@@ -31,7 +31,7 @@ class StatusSuspendedButton extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <a className="dropdown-item" href="" onClick={() => { this.onClickDeactiveBtn() }}>
+      <a className="dropdown-item" onClick={() => { this.onClickDeactiveBtn() }}>
         <i className="icon-fw icon-ban"></i> {t('admin:user_management.user_table.deactivate_account')}
         <i className="icon-fw icon-ban"></i> {t('admin:user_management.user_table.deactivate_account')}
       </a>
       </a>
     );
     );

+ 1 - 1
src/client/js/components/Admin/Users/UserRemoveButton.jsx

@@ -32,7 +32,7 @@ class UserRemoveButton extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
 
 
     return (
     return (
-      <a className="dropdown-item" href="" onClick={() => { this.onClickDeleteBtn() }}>
+      <a className="dropdown-item" onClick={() => { this.onClickDeleteBtn() }}>
         <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
         <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
       </a>
       </a>
     );
     );

+ 3 - 7
src/client/js/components/CreateTemplateModal.jsx

@@ -55,13 +55,9 @@ const CreateTemplateModal = (props) => {
             <code>{parentPath}</code><br />
             <code>{parentPath}</code><br />
             { t('template.modal_label.Create template under') }
             { t('template.modal_label.Create template under') }
           </label>
           </label>
-          <div className="row">
-            <div className="col-md-6">
-              {renderTemplateCard('children', '_template')}
-            </div>
-            <div className="col-md-6">
-              {renderTemplateCard('decendants', '__template')}
-            </div>
+          <div className="card-deck">
+            {renderTemplateCard('children', '_template')}
+            {renderTemplateCard('decendants', '__template')}
           </div>
           </div>
         </div>
         </div>
       </ModalBody>
       </ModalBody>

+ 17 - 17
src/client/js/components/LoginForm.jsx

@@ -44,13 +44,13 @@ class LoginForm extends React.Component {
 
 
     return (
     return (
       <form role="form" action="/login" method="post">
       <form role="form" action="/login" method="post">
-        <div className="input-group mb-3">
+        <div className="input-group">
           <div className="input-group-prepend">
           <div className="input-group-prepend">
             <span className="input-group-text">
             <span className="input-group-text">
               <i className="icon-user"></i>
               <i className="icon-user"></i>
             </span>
             </span>
           </div>
           </div>
-          <input type="text" className="form-control" placeholder="Username or E-mail" name="loginForm[username]" />
+          <input type="text" className="form-control rounded-0" placeholder="Username or E-mail" name="loginForm[username]" />
           {isLdapStrategySetup && (
           {isLdapStrategySetup && (
             <div className="input-group-append">
             <div className="input-group-append">
               <small className="input-group-text text-success">
               <small className="input-group-text text-success">
@@ -60,18 +60,18 @@ class LoginForm extends React.Component {
           )}
           )}
         </div>
         </div>
 
 
-        <div className="input-group mb-3">
+        <div className="input-group">
           <div className="input-group-prepend">
           <div className="input-group-prepend">
             <span className="input-group-text">
             <span className="input-group-text">
               <i className="icon-lock"></i>
               <i className="icon-lock"></i>
             </span>
             </span>
           </div>
           </div>
-          <input type="password" className="form-control" placeholder="Password" name="loginForm[password]" />
+          <input type="password" className="form-control rounded-0" placeholder="Password" name="loginForm[password]" />
         </div>
         </div>
 
 
-        <div className="input-group mt-5">
+        <div className="input-group my-4">
           <input type="hidden" name="_csrf" value={noLoginContainer.csrfToken} />
           <input type="hidden" name="_csrf" value={noLoginContainer.csrfToken} />
-          <button type="submit" id="login" className="btn btn-fill login mx-auto">
+          <button type="submit" id="login" className="btn btn-fill rounded-0 login mx-auto">
             <div className="eff"></div>
             <div className="eff"></div>
             <span className="btn-label">
             <span className="btn-label">
               <i className="icon-login"></i>
               <i className="icon-login"></i>
@@ -96,8 +96,8 @@ class LoginForm extends React.Component {
     };
     };
 
 
     return (
     return (
-      <div key={auth} className="col-6 mb-2">
-        <button type="button" className="btn btn-fill" id={auth} onClick={this.handleLoginWithExternalAuth}>
+      <div key={auth} className="col-6 my-2">
+        <button type="button" className="btn btn-fill rounded-0" id={auth} onClick={this.handleLoginWithExternalAuth}>
           <div className="eff"></div>
           <div className="eff"></div>
           <span className="btn-label">
           <span className="btn-label">
             <i className={`fa fa-${authIconNames[auth]}`}></i>
             <i className={`fa fa-${authIconNames[auth]}`}></i>
@@ -131,7 +131,7 @@ class LoginForm extends React.Component {
         <div className="text-center">
         <div className="text-center">
           <button
           <button
             type="button"
             type="button"
-            className="btn btn-secondary btn-sm mb-3"
+            className="btn btn-secondary btn-sm rounded-0 mb-3"
             data-toggle={isExternalAuthCollapsible ? 'collapse' : ''}
             data-toggle={isExternalAuthCollapsible ? 'collapse' : ''}
             data-target="#external-auth"
             data-target="#external-auth"
             aria-expanded="false"
             aria-expanded="false"
@@ -171,7 +171,7 @@ class LoginForm extends React.Component {
                 <i className="icon-user"></i>
                 <i className="icon-user"></i>
               </span>
               </span>
             </div>
             </div>
-            <input type="text" className="form-control" placeholder={t('User ID')} name="registerForm[username]" defaultValue={username} required />
+            <input type="text" className="form-control rounded-0" placeholder={t('User ID')} name="registerForm[username]" defaultValue={username} required />
           </div>
           </div>
           <p className="form-text text-danger">
           <p className="form-text text-danger">
             <span id="help-block-username"></span>
             <span id="help-block-username"></span>
@@ -183,7 +183,7 @@ class LoginForm extends React.Component {
                 <i className="icon-tag"></i>
                 <i className="icon-tag"></i>
               </span>
               </span>
             </div>
             </div>
-            <input type="text" className="form-control" placeholder={t('Name')} name="registerForm[name]" defaultValue={name} required />
+            <input type="text" className="form-control rounded-0" placeholder={t('Name')} name="registerForm[name]" defaultValue={name} required />
           </div>
           </div>
 
 
           <div className="input-group">
           <div className="input-group">
@@ -192,7 +192,7 @@ class LoginForm extends React.Component {
                 <i className="icon-envelope"></i>
                 <i className="icon-envelope"></i>
               </span>
               </span>
             </div>
             </div>
-            <input type="email" className="form-control" placeholder={t('Email')} name="registerForm[email]" defaultValue={email} required />
+            <input type="email" className="form-control rounded-0" placeholder={t('Email')} name="registerForm[email]" defaultValue={email} required />
           </div>
           </div>
 
 
           {registrationWhiteList.length > 0 && (
           {registrationWhiteList.length > 0 && (
@@ -216,12 +216,12 @@ class LoginForm extends React.Component {
                 <i className="icon-lock"></i>
                 <i className="icon-lock"></i>
               </span>
               </span>
             </div>
             </div>
-            <input type="password" className="form-control" placeholder={t('Password')} name="registerForm[password]" required />
+            <input type="password" className="form-control rounded-0" placeholder={t('Password')} name="registerForm[password]" required />
           </div>
           </div>
 
 
-          <div className="input-group justify-content-center mt-5">
+          <div className="input-group justify-content-center my-4">
             <input type="hidden" name="_csrf" value={noLoginContainer.csrfToken} />
             <input type="hidden" name="_csrf" value={noLoginContainer.csrfToken} />
-            <button type="submit" className="btn btn-fill" id="register">
+            <button type="submit" className="btn btn-fill rounded-0" id="register">
               <div className="eff"></div>
               <div className="eff"></div>
               <span className="btn-label">
               <span className="btn-label">
                 <i className="icon-user-follow"></i>
                 <i className="icon-user-follow"></i>
@@ -231,10 +231,10 @@ class LoginForm extends React.Component {
           </div>
           </div>
         </form>
         </form>
 
 
-        <div className="border-bottom mb-3"></div>
+        <div className="border-bottom"></div>
 
 
         <div className="row">
         <div className="row">
-          <div className="text-right col-12 py-1">
+          <div className="text-right col-12 mt-2 py-2">
             <a href="#login" id="login" className="link-switch" onClick={this.switchForm}>
             <a href="#login" id="login" className="link-switch" onClick={this.switchForm}>
               <i className="icon-fw icon-login"></i>
               <i className="icon-fw icon-login"></i>
               {t('Sign in is here')}
               {t('Sign in is here')}

+ 1 - 1
src/client/js/components/Me/PasswordSettings.jsx

@@ -67,7 +67,7 @@ class PasswordSettings extends React.Component {
 
 
     return (
     return (
       <React.Fragment>
       <React.Fragment>
-        {(!personalContainer.state.isPasswordSet) && <div className="alert alert-warning m-t-10">{ t('Password is not set') }</div>}
+        {(!personalContainer.state.isPasswordSet) && <div className="alert alert-warning">{ t('Password is not set') }</div>}
         <div className="container-fluid my-4">
         <div className="container-fluid my-4">
           {(personalContainer.state.isPasswordSet)
           {(personalContainer.state.isPasswordSet)
             ? <h2 className="border-bottom">{t('personal_settings.update_password')}</h2>
             ? <h2 className="border-bottom">{t('personal_settings.update_password')}</h2>

+ 30 - 32
src/client/js/components/Me/PersonalSettings.jsx

@@ -15,38 +15,36 @@ class PersonalSettings extends React.Component {
 
 
     return (
     return (
       <Fragment>
       <Fragment>
-        <div className="m-t-10">
-          <div className="personal-settings">
-            <ul className="nav nav-tabs" role="tablist">
-              <li className="nav-item">
-                <a className="nav-link active" href="#user-settings" data-toggle="tab" role="tab"><i className="icon-user"></i> { t('User Information') }</a>
-              </li>
-              <li className="nav-item">
-                <a className="nav-link" href="#external-accounts" data-toggle="tab" role="tab">
-                  <i className="icon-share-alt mr-1"></i>
-                  { t('admin:user_management.external_accounts') }
-                </a>
-              </li>
-              <li className="nav-item">
-                <a className="nav-link" href="#password-settings" data-toggle="tab" role="tab"><i className="icon-lock"></i> { t('Password Settings') }</a>
-              </li>
-              <li className="nav-item">
-                <a className="nav-link" href="#apiToken" data-toggle="tab" role="tab"><i className="icon-paper-plane"></i> { t('API Settings') }</a>
-              </li>
-            </ul>
-            <div className="tab-content p-t-10">
-              <div id="user-settings" className="tab-pane active" role="tabpanel">
-                <UserSettings />
-              </div>
-              <div id="external-accounts" className="tab-pane" role="tabpanel">
-                <ExternalAccountLinkedMe />
-              </div>
-              <div id="password-settings" className="tab-pane" role="tabpanel">
-                <PasswordSettings />
-              </div>
-              <div id="apiToken" className="tab-pane" role="tabpanel">
-                <ApiSettings />
-              </div>
+        <div className="personal-settings">
+          <ul className="nav nav-tabs" role="tablist">
+            <li className="nav-item">
+              <a className="nav-link active" href="#user-settings" data-toggle="tab" role="tab"><i className="icon-user"></i> { t('User Information') }</a>
+            </li>
+            <li className="nav-item">
+              <a className="nav-link" href="#external-accounts" data-toggle="tab" role="tab">
+                <i className="icon-share-alt mr-1"></i>
+                { t('admin:user_management.external_accounts') }
+              </a>
+            </li>
+            <li className="nav-item">
+              <a className="nav-link" href="#password-settings" data-toggle="tab" role="tab"><i className="icon-lock"></i> { t('Password Settings') }</a>
+            </li>
+            <li className="nav-item">
+              <a className="nav-link" href="#apiToken" data-toggle="tab" role="tab"><i className="icon-paper-plane"></i> { t('API Settings') }</a>
+            </li>
+          </ul>
+          <div className="tab-content p-t-10">
+            <div id="user-settings" className="tab-pane active" role="tabpanel">
+              <UserSettings />
+            </div>
+            <div id="external-accounts" className="tab-pane" role="tabpanel">
+              <ExternalAccountLinkedMe />
+            </div>
+            <div id="password-settings" className="tab-pane" role="tabpanel">
+              <PasswordSettings />
+            </div>
+            <div id="apiToken" className="tab-pane" role="tabpanel">
+              <ApiSettings />
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>

+ 0 - 5
src/client/js/components/Navbar/PersonalDropdown.jsx

@@ -70,11 +70,6 @@ const PersonalDropdown = (props) => {
 
 
         <div className="dropdown-divider"></div>
         <div className="dropdown-divider"></div>
 
 
-        <a className="dropdown-item" href={`/user/${user.username}#user-draft-list`}><i className="icon-fw icon-docs"></i>{ t('List Drafts') }</a>
-        <a className="dropdown-item" href="/trash"><i className="icon-fw icon-trash"></i>{ t('Deleted Pages') }</a>
-
-        <div className="dropdown-divider"></div>
-
         <h6 className="dropdown-header">Color Scheme</h6>
         <h6 className="dropdown-header">Color Scheme</h6>
         <form className="px-4">
         <form className="px-4">
           <div className="form-row align-items-center">
           <div className="form-row align-items-center">

+ 6 - 8
src/client/js/components/PageCreateModal.jsx

@@ -13,17 +13,16 @@ import { pathUtils } from 'growi-commons';
 import { createSubscribedElement } from './UnstatedUtils';
 import { createSubscribedElement } from './UnstatedUtils';
 
 
 import AppContainer from '../services/AppContainer';
 import AppContainer from '../services/AppContainer';
-import PageContainer from '../services/PageContainer';
 import PagePathAutoComplete from './PagePathAutoComplete';
 import PagePathAutoComplete from './PagePathAutoComplete';
 
 
 const PageCreateModal = (props) => {
 const PageCreateModal = (props) => {
-  const { t, appContainer, pageContainer } = props;
+  const { t, appContainer } = props;
 
 
   const config = appContainer.getConfig();
   const config = appContainer.getConfig();
   const isReachable = config.isSearchServiceReachable;
   const isReachable = config.isSearchServiceReachable;
-  const { path } = pageContainer.state;
+  const { pathname } = window.location;
   const userPageRootPath = userPageRoot(appContainer.currentUser);
   const userPageRootPath = userPageRoot(appContainer.currentUser);
-  const parentPath = pathUtils.addTrailingSlash(path);
+  const parentPath = pathUtils.addTrailingSlash(pathname);
   const now = format(new Date(), 'yyyy/MM/dd');
   const now = format(new Date(), 'yyyy/MM/dd');
 
 
   const [todayInput1, setTodayInput1] = useState(t('Memo'));
   const [todayInput1, setTodayInput1] = useState(t('Memo'));
@@ -152,7 +151,7 @@ const PageCreateModal = (props) => {
                 ? (
                 ? (
                   <PagePathAutoComplete
                   <PagePathAutoComplete
                     crowi={appContainer}
                     crowi={appContainer}
-                    initializedPath={path}
+                    initializedPath={decodeURI(pathname)}
                     addTrailingSlash
                     addTrailingSlash
                     onSubmit={ppacSubmitHandler}
                     onSubmit={ppacSubmitHandler}
                     onInputChange={ppacInputChangeHandler}
                     onInputChange={ppacInputChangeHandler}
@@ -189,7 +188,7 @@ const PageCreateModal = (props) => {
         <fieldset className="col-12">
         <fieldset className="col-12">
 
 
           <h3 className="grw-modal-head pb-2">{ t('template.modal_label.Create template under')}<br />
           <h3 className="grw-modal-head pb-2">{ t('template.modal_label.Create template under')}<br />
-            <code>{path}</code>
+            <code>{decodeURI(pathname)}</code>
           </h3>
           </h3>
 
 
           <div className="d-sm-flex align-items-center justify-items-between">
           <div className="d-sm-flex align-items-center justify-items-between">
@@ -248,14 +247,13 @@ const PageCreateModal = (props) => {
  * Wrapper component for using unstated
  * Wrapper component for using unstated
  */
  */
 const ModalControlWrapper = (props) => {
 const ModalControlWrapper = (props) => {
-  return createSubscribedElement(PageCreateModal, props, [AppContainer, PageContainer]);
+  return createSubscribedElement(PageCreateModal, props, [AppContainer]);
 };
 };
 
 
 
 
 PageCreateModal.propTypes = {
 PageCreateModal.propTypes = {
   t: PropTypes.func.isRequired, //  i18next
   t: PropTypes.func.isRequired, //  i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
 };
 };
 
 
 export default withTranslation()(ModalControlWrapper);
 export default withTranslation()(ModalControlWrapper);

+ 1 - 1
src/client/js/components/PageDeleteModal.jsx

@@ -125,7 +125,7 @@ const PageDeleteModal = (props) => {
       </ModalBody>
       </ModalBody>
       <ModalFooter>
       <ModalFooter>
         <ApiErrorMessage errorCode={errorCode} errorMessage={errorMessage} linkPath={path} />
         <ApiErrorMessage errorCode={errorCode} errorMessage={errorMessage} linkPath={path} />
-        <button type="button" className={`m-l-10 btn btn-${deleteIconAndKey[deleteMode].color}`} onClick={deleteButtonHandler}>
+        <button type="button" className={`btn btn-${deleteIconAndKey[deleteMode].color}`} onClick={deleteButtonHandler}>
           <i className={`icon-${deleteIconAndKey[deleteMode].icon}`} aria-hidden="true"></i>
           <i className={`icon-${deleteIconAndKey[deleteMode].icon}`} aria-hidden="true"></i>
           { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
           { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
         </button>
         </button>

+ 13 - 16
src/client/js/components/PageEditor/CodeMirrorEditor.jsx

@@ -658,12 +658,10 @@ export default class CodeMirrorEditor extends AbstractEditor {
   }
   }
 
 
   getNavbarItems() {
   getNavbarItems() {
-    const buttonColor = '';
     return [
     return [
-      /* eslint-disable max-len */
       <Button
       <Button
         key="nav-item-bold"
         key="nav-item-bold"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Bold"
         title="Bold"
         onClick={this.createReplaceSelectionHandler('**', '**')}
         onClick={this.createReplaceSelectionHandler('**', '**')}
@@ -672,7 +670,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-italic"
         key="nav-item-italic"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Italic"
         title="Italic"
         onClick={this.createReplaceSelectionHandler('*', '*')}
         onClick={this.createReplaceSelectionHandler('*', '*')}
@@ -681,7 +679,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-strikethrough"
         key="nav-item-strikethrough"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Strikethrough"
         title="Strikethrough"
         onClick={this.createReplaceSelectionHandler('~~', '~~')}
         onClick={this.createReplaceSelectionHandler('~~', '~~')}
@@ -690,7 +688,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-header"
         key="nav-item-header"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Heading"
         title="Heading"
         onClick={this.makeHeaderHandler}
         onClick={this.makeHeaderHandler}
@@ -699,7 +697,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-code"
         key="nav-item-code"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Inline Code"
         title="Inline Code"
         onClick={this.createReplaceSelectionHandler('`', '`')}
         onClick={this.createReplaceSelectionHandler('`', '`')}
@@ -708,7 +706,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-quote"
         key="nav-item-quote"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Quote"
         title="Quote"
         onClick={this.createAddPrefixToEachLinesHandler('> ')}
         onClick={this.createAddPrefixToEachLinesHandler('> ')}
@@ -717,7 +715,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-ul"
         key="nav-item-ul"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="List"
         title="List"
         onClick={this.createAddPrefixToEachLinesHandler('- ')}
         onClick={this.createAddPrefixToEachLinesHandler('- ')}
@@ -726,7 +724,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-ol"
         key="nav-item-ol"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Numbered List"
         title="Numbered List"
         onClick={this.createAddPrefixToEachLinesHandler('1. ')}
         onClick={this.createAddPrefixToEachLinesHandler('1. ')}
@@ -735,7 +733,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-checkbox"
         key="nav-item-checkbox"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Check List"
         title="Check List"
         onClick={this.createAddPrefixToEachLinesHandler('- [ ] ')}
         onClick={this.createAddPrefixToEachLinesHandler('- [ ] ')}
@@ -744,7 +742,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-link"
         key="nav-item-link"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Link"
         title="Link"
         onClick={this.createReplaceSelectionHandler('[', ']()')}
         onClick={this.createReplaceSelectionHandler('[', ']()')}
@@ -753,7 +751,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-image"
         key="nav-item-image"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Image"
         title="Image"
         onClick={this.createReplaceSelectionHandler('![', ']()')}
         onClick={this.createReplaceSelectionHandler('![', ']()')}
@@ -762,7 +760,7 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-table"
         key="nav-item-table"
-        color={buttonColor}
+        color={null}
         size="sm"
         size="sm"
         title="Table"
         title="Table"
         onClick={this.showHandsonTableHandler}
         onClick={this.showHandsonTableHandler}
@@ -771,14 +769,13 @@ export default class CodeMirrorEditor extends AbstractEditor {
       </Button>,
       </Button>,
       <Button
       <Button
         key="nav-item-drawio"
         key="nav-item-drawio"
-        color={buttonColor}
+        color={null}
         bssize="small"
         bssize="small"
         title="draw.io"
         title="draw.io"
         onClick={this.showDrawioHandler}
         onClick={this.showDrawioHandler}
       >
       >
         <EditorIcon icon="Drawio" />
         <EditorIcon icon="Drawio" />
       </Button>,
       </Button>,
-      /* eslint-able max-len */
     ];
     ];
   }
   }
 
 

+ 1 - 1
src/client/js/components/PageEditor/OptionsSelector.jsx

@@ -162,7 +162,7 @@ class OptionsSelector extends React.Component {
           toggle={this.onToggleConfigurationDropdown}
           toggle={this.onToggleConfigurationDropdown}
         >
         >
 
 
-          <DropdownToggle color="light" caret>
+          <DropdownToggle color="outline-secondary" caret>
             <i className="icon-settings"></i>
             <i className="icon-settings"></i>
           </DropdownToggle>
           </DropdownToggle>
 
 

+ 9 - 7
src/client/js/components/PageHistory/Revision.jsx

@@ -16,7 +16,8 @@ export default class Revision extends React.Component {
   componentDidMount() {
   componentDidMount() {
   }
   }
 
 
-  _onDiffOpenClicked() {
+  _onDiffOpenClicked(e) {
+    e.preventDefault();
     this.props.onDiffOpenClicked(this.props.revision);
     this.props.onDiffOpenClicked(this.props.revision);
   }
   }
 
 
@@ -35,7 +36,7 @@ export default class Revision extends React.Component {
         <div className="picture-container">
         <div className="picture-container">
           {pic}
           {pic}
         </div>
         </div>
-        <div className="m-l-10">
+        <div className="ml-3">
           <div className="revision-history-meta">
           <div className="revision-history-meta">
             <span className="text-muted small">
             <span className="text-muted small">
               <UserDate dateTime={revision.createdAt} /> ({ t('No diff') })
               <UserDate dateTime={revision.createdAt} /> ({ t('No diff') })
@@ -56,13 +57,13 @@ export default class Revision extends React.Component {
       pic = <UserPicture user={author} size="lg" />;
       pic = <UserPicture user={author} size="lg" />;
     }
     }
 
 
-    const iconClass = this.props.revisionDiffOpened ? 'caret caret-opened' : 'caret';
+    const iconClass = this.props.revisionDiffOpened ? 'fa fa-caret-down caret caret-opened' : 'fa fa-caret-down caret';
     return (
     return (
       <div className="revision-history-main d-flex mt-3">
       <div className="revision-history-main d-flex mt-3">
         <div className="mt-2">
         <div className="mt-2">
           {pic}
           {pic}
         </div>
         </div>
-        <div className="m-l-10">
+        <div className="ml-2">
           <div className="revision-history-author">
           <div className="revision-history-author">
             <strong><Username user={author}></Username></strong>
             <strong><Username user={author}></Username></strong>
           </div>
           </div>
@@ -77,13 +78,14 @@ export default class Revision extends React.Component {
                 }
                 }
                 { this.props.hasDiff
                 { this.props.hasDiff
                   && (
                   && (
-                  <a className="diff-view" onClick={this._onDiffOpenClicked}>
-                    <i className={iconClass}></i> { t('View diff') }
+                  // use dummy href attr (with preventDefault()), because don't apply style by a:not([href])
+                  <a className="diff-view" href="" onClick={this._onDiffOpenClicked}>
+                    <i className={iconClass}></i> {t('View diff')}
                   </a>
                   </a>
                   )
                   )
                 }
                 }
               </span>
               </span>
-              <a href={`?revision=${revision._id}`} className="m-l-10">
+              <a href={`?revision=${revision._id}`} className="ml-2">
                 <i className="icon-login"></i> { t('Go to this version') }
                 <i className="icon-login"></i> { t('Go to this version') }
               </a>
               </a>
             </p>
             </p>

+ 1 - 1
src/client/js/components/RecentCreated/RecentCreated.jsx

@@ -77,7 +77,7 @@ class RecentCreated extends React.Component {
 
 
     return (
     return (
       <div className="page-list-container-create">
       <div className="page-list-container-create">
-        <ul className="page-list-ul page-list-ul-flat">
+        <ul className="page-list-ul page-list-ul-flat mb-3">
           {pageList}
           {pageList}
         </ul>
         </ul>
         <PaginationWrapper
         <PaginationWrapper

+ 15 - 9
src/client/js/components/SavePageControls/GrantSelector.jsx

@@ -30,17 +30,17 @@ class GrantSelector extends React.Component {
 
 
     this.availableGrants = [
     this.availableGrants = [
       {
       {
-        grant: 1, iconClass: 'icon-people', styleClass: '', label: 'Public',
+        grant: 1, iconClass: 'icon-people', btnStyleClass: 'outline-info', label: 'Public',
       },
       },
       {
       {
-        grant: 2, iconClass: 'icon-link', styleClass: 'text-info', label: 'Anyone with the link',
+        grant: 2, iconClass: 'icon-link', btnStyleClass: 'outline-teal', label: 'Anyone with the link',
       },
       },
       // { grant: 3, iconClass: '', label: 'Specified users only' },
       // { grant: 3, iconClass: '', label: 'Specified users only' },
       {
       {
-        grant: 4, iconClass: 'icon-lock', styleClass: 'text-danger', label: 'Only me',
+        grant: 4, iconClass: 'icon-lock', btnStyleClass: 'outline-danger', label: 'Only me',
       },
       },
       {
       {
-        grant: 5, iconClass: 'icon-options', styleClass: '', label: 'Only inside the group', reselectLabel: 'Reselect the group',
+        grant: 5, iconClass: 'icon-options', btnStyleClass: 'outline-purple', label: 'Only inside the group', reselectLabel: 'Reselect the group',
       },
       },
     ];
     ];
 
 
@@ -136,6 +136,7 @@ class GrantSelector extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
     const { grant: currentGrant, grantGroup } = this.state;
     const { grant: currentGrant, grantGroup } = this.state;
 
 
+    let dropdownToggleBtnColor = null;
     let dropdownToggleLabelElm = null;
     let dropdownToggleLabelElm = null;
 
 
     const dropdownMenuElems = this.availableGrants.map((opt) => {
     const dropdownMenuElems = this.availableGrants.map((opt) => {
@@ -143,10 +144,15 @@ class GrantSelector extends React.Component {
         ? opt.reselectLabel // when grantGroup is selected
         ? opt.reselectLabel // when grantGroup is selected
         : opt.label;
         : opt.label;
 
 
-      const labelElm = <span><i className={`icon icon-fw ${opt.iconClass} ${opt.styleClass}`}></i> <span className={opt.styleClass}>{t(label)}</span></span>;
+      const labelElm = (
+        <span>
+          <i className={`icon icon-fw ${opt.iconClass}`}></i> {t(label)}
+        </span>
+      );
 
 
-      // set dropdownToggleLabelElm
+      // set dropdownToggleBtnColor, dropdownToggleLabelElm
       if (opt.grant === 1 || opt.grant === currentGrant) {
       if (opt.grant === 1 || opt.grant === currentGrant) {
+        dropdownToggleBtnColor = opt.btnStyleClass;
         dropdownToggleLabelElm = labelElm;
         dropdownToggleLabelElm = labelElm;
       }
       }
 
 
@@ -155,7 +161,7 @@ class GrantSelector extends React.Component {
 
 
     // add specified group option
     // add specified group option
     if (grantGroup != null) {
     if (grantGroup != null) {
-      const labelElm = <span><i className="icon icon-fw icon-organization text-success"></i> <span className="text-success">{this.getGroupName()}</span></span>;
+      const labelElm = <span><i className="icon icon-fw icon-organization"></i> {this.getGroupName()}</span>;
 
 
       // set dropdownToggleLabelElm
       // set dropdownToggleLabelElm
       dropdownToggleLabelElm = labelElm;
       dropdownToggleLabelElm = labelElm;
@@ -166,7 +172,7 @@ class GrantSelector extends React.Component {
     return (
     return (
       <div className="form-group grw-grant-selector mb-0">
       <div className="form-group grw-grant-selector mb-0">
         <UncontrolledDropdown direction="up" size="sm">
         <UncontrolledDropdown direction="up" size="sm">
-          <DropdownToggle color="light" caret className="d-flex justify-content-between align-items-center" disabled={this.props.disabled}>
+          <DropdownToggle color={dropdownToggleBtnColor} caret className="d-flex justify-content-between align-items-center" disabled={this.props.disabled}>
             {dropdownToggleLabelElm}
             {dropdownToggleLabelElm}
           </DropdownToggle>
           </DropdownToggle>
           <DropdownMenu>
           <DropdownMenu>
@@ -217,7 +223,7 @@ class GrantSelector extends React.Component {
         isOpen={this.state.isSelectGroupModalShown}
         isOpen={this.state.isSelectGroupModalShown}
         toggle={this.hideSelectGroupModal}
         toggle={this.hideSelectGroupModal}
       >
       >
-        <ModalHeader tag="h4" toggle={this.hideSelectGroupModal} className="bg-info text-light">
+        <ModalHeader tag="h4" toggle={this.hideSelectGroupModal} className="bg-purple text-light">
           Select a Group
           Select a Group
         </ModalHeader>
         </ModalHeader>
         <ModalBody>
         <ModalBody>

+ 13 - 8
src/client/js/components/Sidebar/SidebarNav.jsx

@@ -66,6 +66,7 @@ class SidebarNav extends React.Component {
 
 
   render() {
   render() {
     const { isAdmin, currentUsername } = this.props.appContainer;
     const { isAdmin, currentUsername } = this.props.appContainer;
+    const isLoggedIn = currentUsername != null;
 
 
     const primaryItems = [
     const primaryItems = [
       this.generatePrimaryItemObj('custom', 'Custom Sidebar', 'code'),
       this.generatePrimaryItemObj('custom', 'Custom Sidebar', 'code'),
@@ -74,16 +75,20 @@ class SidebarNav extends React.Component {
       // this.generatePrimaryItemObj('favorite', 'Favorite', 'icon-star'),
       // this.generatePrimaryItemObj('favorite', 'Favorite', 'icon-star'),
     ];
     ];
 
 
-    const secondaryItems = [
-      this.generateSecondaryItemObj('draft', 'Draft', 'file_copy', `/user/${currentUsername}#user-draft-list`),
+    let secondaryItems = [
+      isAdmin && (
+        this.generateSecondaryItemObj('admin', 'Admin', 'settings', '/admin')
+      ),
+      isLoggedIn && (
+        this.generateSecondaryItemObj('draft', 'Draft', 'file_copy', `/user/${currentUsername}#user-draft-list`)
+      ),
       this.generateSecondaryItemObj('help', 'Help', 'help', 'https://docs.growi.org', true),
       this.generateSecondaryItemObj('help', 'Help', 'help', 'https://docs.growi.org', true),
-      this.generateSecondaryItemObj('trash', 'Trash', 'delete', '/trash'),
+      isLoggedIn && (
+        this.generateSecondaryItemObj('trash', 'Trash', 'delete', '/trash')
+      ),
     ];
     ];
-    if (isAdmin) {
-      secondaryItems.unshift( // add to the beginning
-        this.generateSecondaryItemObj('admin', 'Admin', 'settings', '/admin'),
-      );
-    }
+    // remove 'false' items
+    secondaryItems = secondaryItems.filter(item => item !== false);
 
 
     return (
     return (
       <GlobalNav
       <GlobalNav

+ 1 - 1
src/client/js/components/User/UserPictureList.jsx

@@ -6,7 +6,7 @@ import UserPicture from './UserPicture';
 export default class UserPictureList extends React.Component {
 export default class UserPictureList extends React.Component {
 
 
   render() {
   render() {
-    return this.state.users.map(user => (
+    return this.props.users.map(user => (
       <span key={user._id}>
       <span key={user._id}>
         <UserPicture user={user} size="xs" />
         <UserPicture user={user} size="xs" />
       </span>
       </span>

+ 17 - 5
src/client/js/services/PageContainer.js

@@ -130,7 +130,6 @@ export default class PageContainer extends Container {
 
 
     const seenUserListElem = document.getElementById('seen-user-list');
     const seenUserListElem = document.getElementById('seen-user-list');
     if (seenUserListElem != null) {
     if (seenUserListElem != null) {
-
       const userIdsStr = seenUserListElem.dataset.userIds;
       const userIdsStr = seenUserListElem.dataset.userIds;
       if (userIdsStr === '') {
       if (userIdsStr === '') {
         return;
         return;
@@ -146,13 +145,11 @@ export default class PageContainer extends Container {
 
 
       const noImageCacheUserIds = noImageCacheUsers.map((user) => { return user.id });
       const noImageCacheUserIds = noImageCacheUsers.map((user) => { return user.id });
       try {
       try {
-        const res = await this.appContainer.apiv3Put('/users/update.imageUrlCache', { userIds: noImageCacheUserIds });
-        const usersUpdated = users.filter((user) => { return user.imageUrlCached }).concat(res.data.updatedUsers);
-        this.setState({ seenUsers: usersUpdated });
+        await this.appContainer.apiv3Put('/users/update.imageUrlCache', { userIds: noImageCacheUserIds });
       }
       }
       catch (err) {
       catch (err) {
+        // Error alert doesn't apear, because user don't need to notice this error.
         logger.error(err);
         logger.error(err);
-        throw new Error(err);
       }
       }
     }
     }
 
 
@@ -163,8 +160,23 @@ export default class PageContainer extends Container {
       if (userIdsStr === '') {
       if (userIdsStr === '') {
         return;
         return;
       }
       }
+
       const { users } = await this.appContainer.apiGet('/users.list', { user_ids: userIdsStr });
       const { users } = await this.appContainer.apiGet('/users.list', { user_ids: userIdsStr });
       this.setState({ likerUsers: users });
       this.setState({ likerUsers: users });
+
+      const noImageCacheUsers = users.filter((user) => { return !user.imageUrlCached });
+      if (noImageCacheUsers.length === 0) {
+        return;
+      }
+
+      const noImageCacheUserIds = noImageCacheUsers.map((user) => { return user.id });
+      try {
+        await this.appContainer.apiv3Put('/users/update.imageUrlCache', { userIds: noImageCacheUserIds });
+      }
+      catch (err) {
+        // Error alert doesn't apear, because user don't need to notice this error.
+        logger.error(err);
+      }
     }
     }
   }
   }
 
 

+ 0 - 78
src/client/styles/agile-admin/inverse/variables.scss

@@ -1,78 +0,0 @@
-// Variables
-
-// @import 'https://fonts.googleapis.com/css?family=Rubik:300,400,500,700,900';
-
-// $basefont1:'Rubik', sans-serif;
-// $basefont2:'Rubik', sans-serif;
-// $basefont1: Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif !default;
-// $basefont2: Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif !default;
-
-/* GROWI Color */
-// $growi-green: #74bc46;
-// $growi-blue: #175fa5;
-
-/*bootstrap Color*/
-// $danger: #ff0a54 !default;
-// $success: #00bb83 !default;
-// $warning: #ffa32b !default;
-// $primary: $growi-blue !default;
-// $info: #009fbb !default;
-// $muted: #98a6ad !default;
-// $dark: #3e4d6c !default;
-// $inverse: #3e4d6c !default;
-// $light: #e4e7ea !default;
-// $extralight: #f7fafc !default;
-
-/*Normal Color*/
-// $white: #ffffff !default;
-// $red: #ff0000 !default;
-// $purple: #7b00ce !default;
-// $blue: #0d00c5 !default;
-// $yellow: #cccf0e !default;
-// $border: #f0f0f0 !default;
-// $megna: #00b5c2 !default;
-
-/*Theme Colors*/
-// $topbar: #3c4451 !default;
-// $sidebar: #4f5467 !default;
-// $bodycolor: #fff !default;
-// $headingtext: #2b2b2b !default;
-// $bodytext: #686868 !default;
-// $linktext: $inverse !default;
-// $linktext-hover: lighten($inverse, 20%) !default;
-// $sidebar-text: #54667a !default;
-// $themecolor: #ff6849 !default;
-// $dark-themecolor: #4f5467 !default;
-
-// $rgt: right !default;
-// $lft: left !default;
-
-// $dark-text: #848a96 !default;
-// $navbar-border: #ccc !default;
-// $active-navbar-border: lighten($navbar-border, 10%) !default;
-// $btn-default-bgcolor: darken(#fff, 10%) !default;
-// $color-inline-code: #c7254e !default;
-// $bgcolor-inline-code: #f9f2f4 !default;
-
-/*Border radius*/
-// $radius: 0 !default;
-
-/*Preloader*/
-/*
-.preloader{
-    width: 100%;
-    height: 100%;
-    top:0px;
-    position: fixed;
-    z-index: 99999;
-    background: #fff;
-    .cssload-speeding-wheel{
-        position: absolute;
-        top: "calc(50% - 3.5px)";
-        left: "calc(50% - 3.5px)";
-    }
-}
-*/
-
-/*Font weight*/
-// $font-bold: 700 !default;

+ 0 - 1
src/client/styles/scss/_editor-attachment.scss

@@ -108,7 +108,6 @@
     border: none;
     border: none;
     border-top: 1px dotted #ccc;
     border-top: 1px dotted #ccc;
     border-bottom: none;
     border-bottom: none;
-    border-radius: 0;
 
 
     &:active {
     &:active {
       box-shadow: none;
       box-shadow: none;

+ 2 - 1
src/client/styles/scss/_hljs.scss

@@ -2,7 +2,8 @@ pre.hljs {
   position: relative;
   position: relative;
 
 
   // override Highlight Js Style Border
   // override Highlight Js Style Border
-  border-radius: 3px;
+  border: 1px solid $gray-500;
+  border-radius: $border-radius;
   &.hljs-no-border {
   &.hljs-no-border {
     border: none;
     border: none;
   }
   }

+ 1 - 24
src/client/styles/scss/_layout.scss

@@ -1,5 +1,3 @@
-@import 'layout_variable';
-
 // FIXME: replace with mt-2 or mt-3
 // FIXME: replace with mt-2 or mt-3
 .grw-mt-10px {
 .grw-mt-10px {
   margin-top: 10px !important;
   margin-top: 10px !important;
@@ -29,33 +27,13 @@
 
 
 .grw-modal-head {
 .grw-modal-head {
   font-size: 1em;
   font-size: 1em;
-  border-bottom: 1px solid $grw-line-gray;
+  border-bottom: 1px solid $gray-500;
 }
 }
 
 
 .main {
 .main {
   margin-top: 1rem;
   margin-top: 1rem;
 }
 }
 
 
-.layout-control {
-  position: fixed;
-  right: 25%;
-  bottom: 25px;
-  z-index: 1;
-  display: block;
-  padding: 5px 8px;
-  font-size: 0.8em;
-  text-align: center;
-  border: solid 1px #ccc;
-  border-right: none;
-  border-radius: 5px 0 0 5px;
-  transition: 0.3s ease;
-
-  &:hover {
-    text-decoration: none;
-    cursor: pointer;
-  }
-}
-
 .revision-toc {
 .revision-toc {
   // to get on the Attachment row
   // to get on the Attachment row
   z-index: 1;
   z-index: 1;
@@ -114,7 +92,6 @@
       margin-bottom: 20px;
       margin-bottom: 20px;
       font-size: 0.9em;
       font-size: 0.9em;
       border: solid 1px #aaa;
       border: solid 1px #aaa;
-      border-radius: 5px;
 
 
       .revision-toc-head {
       .revision-toc-head {
         display: inline-block;
         display: inline-block;

+ 1 - 2
src/client/styles/scss/_layout_growi.scss

@@ -1,4 +1,3 @@
-@import 'layout_variable';
 @import 'layout';
 @import 'layout';
 
 
 .growi {
 .growi {
@@ -10,7 +9,7 @@
     // adjusting position with negative margin
     // adjusting position with negative margin
     height: $grw-nav-main-tab-height;
     height: $grw-nav-main-tab-height;
     line-height: 1.25;
     line-height: 1.25;
-    border-bottom: 1px solid $grw-line-gray;
+    border-bottom: 1px solid transparent;
 
 
     .liker-user-count,
     .liker-user-count,
     .seen-user-count {
     .seen-user-count {

+ 0 - 8
src/client/styles/scss/_layout_variable.scss

@@ -1,8 +0,0 @@
-/* color variables */
-
-/* blue */
-$grw-alice-blue: aliceblue;
-
-/* gray */
-$grw-line-gray: #dee2e6;
-$grw-line-light-gray: #ddd;

+ 0 - 2
src/client/styles/scss/_mixins.scss

@@ -1,5 +1,3 @@
-@import 'layout_variable';
-
 @mixin variable-font-size($basesize) {
 @mixin variable-font-size($basesize) {
   font-size: $basesize * 0.6;
   font-size: $basesize * 0.6;
 
 

+ 0 - 1
src/client/styles/scss/_on-edit.scss

@@ -1,5 +1,4 @@
 @import 'editor-overlay';
 @import 'editor-overlay';
-@import 'layout_variable';
 
 
 body:not(.on-edit) {
 body:not(.on-edit) {
   // hide .page-editor-footer
   // hide .page-editor-footer

+ 13 - 27
src/client/styles/scss/_override-bootstrap-variables.scss

@@ -11,7 +11,7 @@ $success: #00bb83 !default;
 $warning: #ffa32b !default;
 $warning: #ffa32b !default;
 $danger: #ff0a54 !default;
 $danger: #ff0a54 !default;
 $light: #e4e7ea !default;
 $light: #e4e7ea !default;
-$dark: #3e4d6c !default;
+$dark: #343a40 !default;
 
 
 //== Typography
 //== Typography
 //
 //
@@ -26,33 +26,21 @@ $line-height-base: 1.42857;
 
 
 //== Components
 //== Components
 //
 //
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-$border-radius-base: 0;
-$border-radius-large: 0;
-$border-radius-small: 0;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-$btn-border-radius: 0;
-$btn-border-radius-lg: 0;
-$btn-border-radius-sm: 0;
-
+$border-radius:               .15rem;
+$border-radius-sm:            .1rem;
+$border-radius-lg:            .25rem;
+$border-radius-xl:            .35rem;
 
 
 
 
 //== Forms
 //== Forms
 //
 //
-$input-border-radius: 0;
-$input-border-radius-lg: 0;
-$input-border-radius-sm: 0;
+$input-border-radius: $border-radius-sm;
+$input-border-radius-sm: $border-radius-sm;
+$input-border-radius-lg: $border-radius;
 
 
 //== Navs
 //== Navs
-
 $nav-link-padding-y: 0.75rem;
 $nav-link-padding-y: 0.75rem;
 $nav-link-padding-x: 1rem;
 $nav-link-padding-x: 1rem;
-$nav-tabs-border-radius: 0;
 
 
 //== Navbar
 //== Navbar
 $navbar-padding-y: 0;
 $navbar-padding-y: 0;
@@ -60,28 +48,26 @@ $navbar-brand-padding-y: 0;
 $navbar-nav-link-padding-x: 1rem;
 $navbar-nav-link-padding-x: 1rem;
 
 
 //== Dropdowns
 //== Dropdowns
-$dropdown-border-radius: 0;
+$dropdown-border-radius: $border-radius-sm;
 
 
 //== card
 //== card
-$card-border-radius: 0;
 $card-spacer-y: 7px;
 $card-spacer-y: 7px;
 $card-spacer-x: 15px;
 $card-spacer-x: 15px;
 
 
 //== Modals
 //== Modals
 $modal-content-border-width: 0;
 $modal-content-border-width: 0;
-$modal-content-border-radius: 0;
 $modal-header-padding-y: 0.75rem;
 $modal-header-padding-y: 0.75rem;
 $modal-header-padding-x: 1rem;
 $modal-header-padding-x: 1rem;
 
 
-//== Alerts
-$alert-border-radius: 0;
-
 //== Progress bar
 //== Progress bar
 $progress-height: 4px;
 $progress-height: 4px;
-$progress-border-radius: 0;
+$progress-border-radius: $border-radius-sm;
 $progress-bg: #f0f0f0;
 $progress-bg: #f0f0f0;
 $progress-box-shadow: none;
 $progress-box-shadow: none;
 
 
+//== Code
+$pre-color: dummyinvalildcolor; // disable pre color specification with invalid value
+
 //== Custom Checkbox
 //== Custom Checkbox
 $custom-checkbox-indicator-border-radius: 0px;
 $custom-checkbox-indicator-border-radius: 0px;
 $custom-control-indicator-focus-box-shadow: none;
 $custom-control-indicator-focus-box-shadow: none;

+ 0 - 9
src/client/styles/scss/_override-bootstrap.scss

@@ -39,11 +39,6 @@
     line-height: 14px;
     line-height: 14px;
   }
   }
 
 
-  code {
-    padding: 2px 4px;
-    font-size: 90%;
-  }
-
   // Navs
   // Navs
   .nav-tabs {
   .nav-tabs {
     .nav-item {
     .nav-item {
@@ -65,24 +60,20 @@
   // card (substitute panel of bootstrap3)
   // card (substitute panel of bootstrap3)
   .card {
   .card {
     margin-bottom: 20px;
     margin-bottom: 20px;
-    border-radius: $card-border-radius;
   }
   }
 
 
   .card-header {
   .card-header {
     font-weight: 700;
     font-weight: 700;
     text-transform: none;
     text-transform: none;
-    border-radius: $card-border-radius;
   }
   }
 
 
   .card-header:first-child {
   .card-header:first-child {
-    border-radius: $card-border-radius;
   }
   }
 
 
   // Well (substitute Well of bootstrap3)
   // Well (substitute Well of bootstrap3)
   .card.well {
   .card.well {
     min-height: 20px;
     min-height: 20px;
     padding: $card-spacer-y $card-spacer-x;
     padding: $card-spacer-y $card-spacer-x;
-    border-radius: 3px;
   }
   }
 
 
   // Dropdowns
   // Dropdowns

+ 1 - 9
src/client/styles/scss/_search.scss

@@ -1,5 +1,3 @@
-@import 'layout_variable';
-
 .search-listpage-icon {
 .search-listpage-icon {
   font-size: 16px;
   font-size: 16px;
   color: #999;
   color: #999;
@@ -22,7 +20,7 @@
 
 
   .search-clear {
   .search-clear {
     position: absolute;
     position: absolute;
-    top: 4px;
+    top: 5px;
     right: 4px;
     right: 4px;
     z-index: 3;
     z-index: 3;
     width: 24px;
     width: 24px;
@@ -187,7 +185,6 @@
         padding: 16px;
         padding: 16px;
         font-size: 13px;
         font-size: 13px;
         border: solid 1px #ccc;
         border: solid 1px #ccc;
-        border-radius: 3px;
       }
       }
     }
     }
   }
   }
@@ -212,9 +209,4 @@
   caption {
   caption {
     display: table-header-group;
     display: table-header-group;
   }
   }
-
-  code {
-    padding: 0.25em;
-    background: $grw-alice-blue;
-  }
 }
 }

+ 13 - 0
src/client/styles/scss/_vendor-presentation.scss

@@ -0,0 +1,13 @@
+// import bootstrap configurations
+@import '~bootstrap/scss/functions';
+@import '~bootstrap/scss/variables';
+@import '~bootstrap/scss/mixins';
+@import '~bootstrap/scss/utilities';
+
+@import '~reveal.js/css/reveal.css';
+@import '~reveal.js/css/theme/black.css';
+
+// hljs
+.reveal {
+  @import 'hljs';
+}

+ 1 - 12
src/client/styles/scss/_wiki.scss

@@ -1,5 +1,3 @@
-@import 'layout_variable';
-
 div.body {
 div.body {
   padding: 10px;
   padding: 10px;
 }
 }
@@ -36,7 +34,7 @@ div.body {
     margin-top: 2em;
     margin-top: 2em;
     font-size: 1.8em;
     font-size: 1.8em;
     line-height: 1.1em;
     line-height: 1.1em;
-    border-bottom: solid 1px $grw-line-light-gray;
+    border-bottom: solid 1px transparent;
   }
   }
   h2 {
   h2 {
     padding-bottom: 0.5em;
     padding-bottom: 0.5em;
@@ -127,15 +125,6 @@ div.body {
     }
     }
   }
   }
 
 
-  pre {
-    white-space: pre-line;
-  }
-
-  // only inline code blocks
-  p code {
-    font-family: $font-family-monospace-not-strictly;
-  }
-
   .page-template-builder {
   .page-template-builder {
     position: relative;
     position: relative;
 
 

+ 11 - 0
src/client/styles/scss/atoms/_code.scss

@@ -0,0 +1,11 @@
+/*
+ * style of inline-code
+ */
+:not(pre) {
+  > code {
+    padding: 2px 4px;
+    font-family: $font-family-monospace-not-strictly;
+    border: 1px solid;
+    border-radius: $border-radius;
+  }
+}

+ 4 - 0
src/client/styles/scss/atoms/_pre.scss

@@ -0,0 +1,4 @@
+pre {
+  padding: 0.5em;
+  border-radius: $border-radius;
+}

+ 2 - 2
src/client/styles/scss/style-app.scss

@@ -1,5 +1,4 @@
 // import variables
 // import variables
-@import '../agile-admin/inverse/variables';
 @import 'variables';
 @import 'variables';
 
 
 @import 'mixins';
 @import 'mixins';
@@ -16,7 +15,9 @@
 
 
 // atoms
 // atoms
 @import 'atoms/buttons';
 @import 'atoms/buttons';
+@import 'atoms/code';
 @import 'atoms/nav';
 @import 'atoms/nav';
+@import 'atoms/pre';
 @import 'atoms/spinners';
 @import 'atoms/spinners';
 @import 'atoms/custom_control';
 @import 'atoms/custom_control';
 
 
@@ -39,7 +40,6 @@
 @import 'layout';
 @import 'layout';
 @import 'layout_growi';
 @import 'layout_growi';
 @import 'layout_kibela';
 @import 'layout_kibela';
-@import 'layout_variable';
 @import 'login';
 @import 'login';
 @import 'me';
 @import 'me';
 @import 'navbar';
 @import 'navbar';

+ 4 - 7
src/client/styles/scss/style-presentation.scss

@@ -1,13 +1,10 @@
-// import Growi variable
+// import variable
 @import 'variables';
 @import 'variables';
 
 
-@import '~reveal.js/css/reveal.css';
-@import '~reveal.js/css/theme/black.css';
+@import 'mixins';
+@import 'override-bootstrap-variables';
 
 
-// hljs
-.reveal {
-  @import 'hljs';
-}
+@import 'vendor-presentation';
 
 
 .reveal {
 .reveal {
   font-size: 32px;
   font-size: 32px;

+ 21 - 59
src/client/styles/scss/theme/_apply-colors-dark.scss

@@ -1,5 +1,19 @@
 // determine optional variables
 // determine optional variables
 $bgcolor-subnabvar: lighten($bgcolor-global, 3%) !default;
 $bgcolor-subnabvar: lighten($bgcolor-global, 3%) !default;
+$color-table: white !default;
+$bgcolor-table: #343a40 !default;
+$border-color-table: lighten($bgcolor-table, 7.5%) !default;
+$color-table-hover: rgba(white, 0.075) !default;
+$bgcolor-table-hover: lighten($bgcolor-table, 7.5%) !default;
+
+// override bootstrap variables
+$table-dark-color: $color-table;
+$table-dark-bg: $bgcolor-table;
+$table-dark-border-color: $border-color-table;
+$table-dark-hover-color: $color-table-hover;
+$table-dark-hover-bg: $bgcolor-table-hover;
+
+@import 'reboot-bootstrap-tables';
 
 
 /*
 /*
   * Form
   * Form
@@ -39,20 +53,6 @@ textarea.form-control {
   }
   }
 }
 }
 
 
-/*
- * Panel
- */
-.panel {
-  &,
-  &.panel-white,
-  &.panel-default {
-    .panel-heading,
-    .panel-body {
-      color: theme-color('light');
-    }
-  }
-}
-
 /*
 /*
  * Table
  * Table
  */
  */
@@ -83,38 +83,6 @@ ul.pagination {
   }
   }
 }
 }
 
 
-.table > thead > tr > th,
-.table > tbody > tr > th,
-.table > tfoot > tr > th,
-.table > thead > tr > td,
-.table > tbody > tr > td,
-.table > tfoot > tr > td,
-.table > thead > tr > th,
-.table-bordered {
-  // FIXME: use $table-dark-*
-  // border-top: 1px solid $border;
-}
-
-.table-bordered > thead > tr > th,
-.table-bordered > tbody > tr > th,
-.table-bordered > tfoot > tr > th,
-.table-bordered > thead > tr > td,
-.table-bordered > tbody > tr > td,
-.table-bordered > tfoot > tr > td {
-  // FIXME: use $table-dark-*
-  // border: 1px solid $border;
-}
-
-.table > thead > tr > th {
-  // FIXME: use $table-dark-*
-  // border-bottom: 1px solid $border;
-}
-
-.table-bordered {
-  // FIXME: use $table-dark-*
-  // border: 1px solid $border;
-}
-
 /*
 /*
  * GROWI page list
  * GROWI page list
  */
  */
@@ -138,15 +106,11 @@ ul.pagination {
   background-color: $bgcolor-subnabvar;
   background-color: $bgcolor-subnabvar;
 }
 }
 
 
-/*
- * GROWI search page
- */
-.search-page {
-  .input-group-btn {
-    .btn-light {
-      // FIXME:
-      // border: 1px solid darken($border, 30%); // fit to input.form-control
-    }
+// Search drop down
+#search-typeahead-asynctypeahead {
+  background-color: $bgcolor-global;
+  .table {
+    background-color: transparent;
   }
   }
 }
 }
 
 
@@ -161,12 +125,10 @@ ul.pagination {
 
 
 .wiki {
 .wiki {
   h1 {
   h1 {
-    // FIXME:
-    // border-color: lighten($border, 10%);
+    border-color: lighten($border-color-theme, 10%);
   }
   }
   h2 {
   h2 {
-    // FIXME:
-    // border-color: $border;
+    border-color: $border-color-theme;
   }
   }
 }
 }
 
 

+ 5 - 0
src/client/styles/scss/theme/_apply-colors-kibela.scss

@@ -123,6 +123,9 @@ body.kibela {
   }
   }
 
 
   /* Modal */
   /* Modal */
+  .modal-title {
+    color: #ffffff; // override header colors
+  }
   .modal-content {
   .modal-content {
     background-color: $themelight;
     background-color: $themelight;
   }
   }
@@ -131,6 +134,8 @@ body.kibela {
   :not(.hljs) > code:not(.hljs) {
   :not(.hljs) > code:not(.hljs) {
     color: $color-inline-code;
     color: $color-inline-code;
     background-color: $bgcolor-inline-code;
     background-color: $bgcolor-inline-code;
+    border: solid 1px $bordercolor-inline-code;
+    border-radius: 0.35em;
   }
   }
 
 
   /* button */
   /* button */

+ 14 - 0
src/client/styles/scss/theme/_apply-colors-light.scss

@@ -1,5 +1,19 @@
 // determine optional variables
 // determine optional variables
 $bgcolor-subnabvar: darken($bgcolor-global, 3%) !default;
 $bgcolor-subnabvar: darken($bgcolor-global, 3%) !default;
+$color-table: $color-global !default;
+$bgcolor-table: null !default;
+$border-color-table: #dee2e6 !default;
+$color-table-hover: $color-table !default;
+$bgcolor-table-hover: rgba(black, 0.075) !default;
+
+// override bootstrap variables
+$table-color: $color-table;
+$table-bg: $bgcolor-table;
+$table-border-color: $border-color-table;
+$table-hover-color: $color-table-hover;
+$table-hover-bg: $bgcolor-table-hover;
+
+@import 'reboot-bootstrap-tables';
 
 
 /*
 /*
  * Form
  * Form

+ 35 - 9
src/client/styles/scss/theme/_apply-colors.scss

@@ -13,6 +13,13 @@ $bgcolor-search-top-dropdown: $secondary !default;
 $bgcolor-sidebar-nav-item-active: darken($bgcolor-sidebar, 10%) !default;
 $bgcolor-sidebar-nav-item-active: darken($bgcolor-sidebar, 10%) !default;
 $text-shadow-sidebar-nav-item-active: 1px 1px 2px $primary !default;
 $text-shadow-sidebar-nav-item-active: 1px 1px 2px $primary !default;
 $bgcolor-sidebar-list-group: $bgcolor-list !default;
 $bgcolor-sidebar-list-group: $bgcolor-list !default;
+$bgcolor-inline-code: #f0f0f0 !default;
+$color-inline-code: #c7254e !default;
+$bordercolor-inline-code: #ccc8c8 !default;
+$bordercolor-nav-tabs: #dee2e6 !default;
+$bordercolor-nav-tabs-hover: #e9ecef #e9ecef $bordercolor-nav-tabs !default;
+$color-nav-tabs-link-active: #495057 !default;
+$bordercolor-nav-tabs-active: $bordercolor-nav-tabs $bordercolor-nav-tabs $bgcolor-global !default;
 
 
 // override bootstrap variables
 // override bootstrap variables
 $body-bg: $bgcolor-global;
 $body-bg: $bgcolor-global;
@@ -20,17 +27,40 @@ $body-color: $color-global;
 $link-color: $color-link;
 $link-color: $color-link;
 $link-hover-color: $color-link-hover;
 $link-hover-color: $color-link-hover;
 $input-focus-color: $color-global;
 $input-focus-color: $color-global;
+$nav-tabs-border-color: $bordercolor-nav-tabs;
+$nav-tabs-link-hover-border-color: $bordercolor-nav-tabs-hover;
+$nav-tabs-link-active-color: $color-nav-tabs-link-active;
+$nav-tabs-link-active-bg: $bgcolor-global;
+$nav-tabs-link-active-border-color: $bordercolor-nav-tabs-active;
 
 
 @import '~bootstrap/scss/functions';
 @import '~bootstrap/scss/functions';
 @import '~bootstrap/scss/variables';
 @import '~bootstrap/scss/variables';
 @import '~bootstrap/scss/mixins';
 @import '~bootstrap/scss/mixins';
 @import '../mixins';
 @import '../mixins';
-@import 'mixins-for-tables';
 @import 'mixins/list-group';
 @import 'mixins/list-group';
+@import 'mixins/tables'; // comment out and use _reboot-bootstrap-tables instead -- 2020.05.28 Yuki Takei
 @import 'reboot-bootstrap-colors';
 @import 'reboot-bootstrap-colors';
 @import 'reboot-bootstrap-theme-colors';
 @import 'reboot-bootstrap-theme-colors';
+@import 'reboot-bootstrap-nav';
 @import 'reboot-toastr-colors';
 @import 'reboot-toastr-colors';
 
 
+:not(pre) {
+  > code {
+    color: $color-inline-code;
+    background-color: $bgcolor-inline-code;
+    border-color: $bordercolor-inline-code;
+  }
+}
+
+pre:not(.hljs):not(.CodeMirror-line) {
+  background-color: $bgcolor-inline-code;
+  border-color: $bordercolor-inline-code;
+}
+
+//
+//== Apply to Bootstrap Elements
+//
+
 // Link buttons
 // Link buttons
 .btn-link {
 .btn-link {
   color: $link-color;
   color: $link-color;
@@ -176,14 +206,6 @@ $input-focus-color: $color-global;
   fill: $color-editor-icons;
   fill: $color-editor-icons;
 }
 }
 
 
-/*
- * code color of inline-code
- */
-:not(.hljs) > code:not(.hljs) {
-  color: $color-inline-code;
-  background-color: $bgcolor-inline-code;
-}
-
 /*
 /*
  * Modal
  * Modal
  */
  */
@@ -208,6 +230,10 @@ $input-focus-color: $color-global;
   }
   }
 }
 }
 
 
+.liker-and-seenusers {
+  border-bottom-color: $bordercolor-nav-tabs;
+}
+
 /*
 /*
  * cards
  * cards
  */
  */

+ 0 - 34
src/client/styles/scss/theme/_mixins-for-tables.scss

@@ -1,34 +0,0 @@
-//== Table
-$table-variants: (
-  'light': $light,
-  'dark': $dark,
-);
-
-// remove when master version is released
-// show https://github.com/twbs/bootstrap/blob/28cb1ff2b23253293601c51aff434c39b461025e/scss/mixins/_table-variants.scss
-@mixin table-variant($state, $background) {
-  .table-#{$state} {
-    $table-hover-bg-factor: 0.075 !default;
-    $table-striped-bg-factor: 0.05 !default;
-    $body-bg: $white !default;
-    $table-active-bg-factor: 0.1 !default;
-    $table-border-factor: 0.1 !default;
-
-    $color: color-contrast(mix(rgba($background, 1), $body-bg, opacity($background) * 100));
-    $color: gray;
-    $hover-bg: mix($color, $background, percentage($table-hover-bg-factor));
-    $striped-bg: mix($color, $background, percentage($table-striped-bg-factor));
-    $active-bg: mix($color, $background, percentage($table-active-bg-factor));
-
-    --bs-table-bg: #{$background};
-    --bs-table-striped-bg: #{$striped-bg};
-    --bs-table-striped-color: #{color-contrast($striped-bg)};
-    --bs-table-active-bg: #{$active-bg};
-    --bs-table-active-color: #{color-contrast($active-bg)};
-    --bs-table-hover-bg: #{$hover-bg};
-    --bs-table-hover-color: #{color-contrast($hover-bg)};
-
-    color: $color;
-    border-color: mix($color, $background, percentage($table-border-factor));
-  }
-}

+ 0 - 2
src/client/styles/scss/theme/_reboot-bootstrap-colors.scss

@@ -25,9 +25,7 @@ body {
   background-color: $body-bg; // 2
   background-color: $body-bg; // 2
 }
 }
 
 
-//
 // Links
 // Links
-//
 
 
 a {
 a {
   color: $link-color;
   color: $link-color;

+ 41 - 0
src/client/styles/scss/theme/_reboot-bootstrap-nav.scss

@@ -0,0 +1,41 @@
+//
+//
+// Apply partially
+//   https://github.com/twbs/bootstrap/blob/v4.5.0/scss/_nav.scss
+//
+//
+
+//
+// Tabs
+//
+
+.nav-tabs {
+  border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
+
+  .nav-link {
+    border: $nav-tabs-border-width solid transparent;
+    @include border-top-radius($nav-tabs-border-radius);
+
+    @include hover-focus() {
+      border-color: $nav-tabs-link-hover-border-color;
+    }
+
+    &.disabled {
+      color: $nav-link-disabled-color;
+      background-color: transparent;
+      border-color: transparent;
+    }
+  }
+
+  .nav-link.active,
+  .nav-item.show .nav-link {
+    color: $nav-tabs-link-active-color;
+    background-color: $nav-tabs-link-active-bg;
+    border-color: $nav-tabs-link-active-border-color;
+  }
+
+  .dropdown-menu {
+    // Remove the top rounded corners here since there is a hard edge above the menu
+    @include border-top-radius(0);
+  }
+}

+ 72 - 0
src/client/styles/scss/theme/_reboot-bootstrap-tables.scss

@@ -0,0 +1,72 @@
+//
+//
+// Apply partially
+//   https://github.com/twbs/bootstrap/blob/v4.5.0/scss/_tables.scss
+//
+//
+
+.table {
+  color: $table-color;
+  background-color: $table-bg; // Reset for nesting within parents with `background-color`.
+
+  th,
+  td {
+    border-top-color: $table-border-color;
+  }
+
+  thead th {
+    border-bottom-color: $table-border-color;
+  }
+
+  tbody + tbody {
+    border-top-color: $table-border-color;
+  }
+}
+
+.table-bordered {
+  border-color: $table-border-color;
+
+  th,
+  td {
+    border-color: $table-border-color;
+  }
+}
+
+.table-hover {
+  tbody tr {
+    @include hover() {
+      color: $table-hover-color;
+      background-color: $table-hover-bg;
+    }
+  }
+}
+
+.table-dark {
+  color: $table-dark-color;
+  background-color: $table-dark-bg;
+
+  th,
+  td,
+  thead th {
+    border-color: $table-dark-border-color;
+  }
+
+  &.table-bordered {
+    border: 0;
+  }
+
+  &.table-striped {
+    tbody tr:nth-of-type(#{$table-striped-order}) {
+      background-color: $table-dark-accent-bg;
+    }
+  }
+
+  &.table-hover {
+    tbody tr {
+      @include hover() {
+        color: $table-dark-hover-color;
+        background-color: $table-dark-hover-bg;
+      }
+    }
+  }
+}

+ 10 - 4
src/client/styles/scss/theme/_reboot-bootstrap-theme-colors.scss

@@ -4,6 +4,16 @@ $theme-colors: map-merge($theme-colors, $colors);
   @include bg-variant('.bg-#{$color}', $value);
   @include bg-variant('.bg-#{$color}', $value);
 }
 }
 
 
+@each $color, $value in $theme-colors {
+  .border-#{$color} {
+    border-color: $value !important;
+  }
+}
+
+@each $color, $value in $theme-colors {
+  @include text-emphasis-variant('.text-#{$color}', $value, true);
+}
+
 @each $color, $value in $theme-colors {
 @each $color, $value in $theme-colors {
   .btn-#{$color} {
   .btn-#{$color} {
     @include button-variant($value, $value);
     @include button-variant($value, $value);
@@ -65,7 +75,3 @@ $theme-colors: map-merge($theme-colors, $colors);
     background: $color;
     background: $color;
   }
   }
 }
 }
-
-@each $color, $value in $table-variants {
-  @include table-variant($color, $value);
-}

+ 28 - 11
src/client/styles/scss/theme/antarctic.scss

@@ -49,19 +49,19 @@ html[dark] {
 
 
   // Background colors
   // Background colors
   $bgcolor-global: $themelight;
   $bgcolor-global: $themelight;
-  $bgcolor-inline-code: #f9f2f4;
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
 
 
   // Font colors
   // Font colors
   $color-global: black;
   $color-global: black;
   $color-reversal: #eeeeee;
   $color-reversal: #eeeeee;
   // $color-header: #2b2b2b;
   // $color-header: #2b2b2b;
-  $color-link: lighten($color-global, 20%);
+  $color-link: lighten($themecolor, 20%);
   $color-link-hover: lighten($color-link, 20%);
   $color-link-hover: lighten($color-link, 20%);
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-nabvar: $color-reversal;
   $color-link-nabvar: $color-reversal;
-  $color-inline-code: #c7254e;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   $color-list: $color-global;
   $color-list: $color-global;
@@ -71,24 +71,34 @@ html[dark] {
   $color-list-hover: $color-reversal;
   $color-list-hover: $color-reversal;
 
 
   // Navbar
   // Navbar
-  $bgcolor-navbar: $themecolor;
-  $border-color-navbar-gradient-left: #545fff;
-  $border-color-navbar-gradient-right: #00a6e5;
-
+  $bgcolor-navbar: #35393f;
+  $bgcolor-search-top-dropdown: #fa9913;
+  $border-image-navbar: linear-gradient(to right, #f6d02e 0%, #f87c00 47%, #f6d02e 100%);
   // Logo colors
   // Logo colors
   $bgcolor-logo: $bgcolor-navbar;
   $bgcolor-logo: $bgcolor-navbar;
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
 
 
   // Sidebar
   // Sidebar
-  $bgcolor-sidebar: $bgcolor-navbar;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-navbar, 10%);
+  $bgcolor-sidebar: $themecolor;
+  $bgcolor-sidebar-nav-item-active: rgba(#000000, 0.37); // optional
+  $text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+  // Sidebar resize button
+  $color-resize-button: $color-reversal;
+  $bgcolor-resize-button: #fa9913;
+  $color-resize-button-hover: $color-reversal;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
+  // Sidebar contents
+  $color-sidebar-context: $themecolor;
+  $bgcolor-sidebar-context: #f4f6fc;
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #fafbff; // optional
 
 
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;
@@ -110,6 +120,13 @@ html[dark] {
   .table {
   .table {
     background-color: $themelight;
     background-color: $themelight;
   }
   }
+
+  #search-typeahead-asynctypeahead {
+    background-color: $bgcolor-global;
+    .table {
+      background-color: transparent;
+    }
+  }
 }
 }
 
 
 //== Dark Mode
 //== Dark Mode
@@ -134,7 +151,7 @@ html[dark] {
 //   $color-link-wiki: lighten($basecolor, 50%);
 //   $color-link-wiki: lighten($basecolor, 50%);
 //   $color-link-wiki-hover: darken($color-link-wiki, 5%);
 //   $color-link-wiki-hover: darken($color-link-wiki, 5%);
 //   $color-link-nabvar: $color-global;
 //   $color-link-nabvar: $color-global;
-//   $color-inline-code: #c7254e;
+//   $color-inline-code: #c7254e; // optional
 
 
 //   // List Group colors
 //   // List Group colors
 //   $color-list: $color-global;
 //   $color-list: $color-global;

+ 30 - 54
src/client/styles/scss/theme/christmas.scss

@@ -12,20 +12,17 @@
 // $danger: #;
 // $danger: #;
 // $light: #;
 // $light: #;
 // $dark: #;
 // $dark: #;
+
 $themecolor: #b3000c;
 $themecolor: #b3000c;
 $themelight: white;
 $themelight: white;
-
-$subthemecolor: #017e20;
+$subthemecolor: #30882c;
 $bgcolor-global: $themelight;
 $bgcolor-global: $themelight;
-$linktext: lighten(#0d5901, 5%);
-$linktext-hover: lighten($linktext, 12%);
+$linktext: $subthemecolor;
+$linktext-hover: lighten($subthemecolor, 15%);
 $sidebar-text: #ffffff;
 $sidebar-text: #ffffff;
 $fillcolor-logo-mark: lighten(desaturate($themecolor, 50%), 50%);
 $fillcolor-logo-mark: lighten(desaturate($themecolor, 50%), 50%);
-$color-link-wiki: lighten($themecolor, 5%);
+$color-link-wiki: lighten($subthemecolor, 5%);
 $color-link-wiki-hover: lighten($color-link-wiki, 15%);
 $color-link-wiki-hover: lighten($color-link-wiki, 15%);
-$color-inline-code: darken($subthemecolor, 5%);
-$bgcolor-inline-code: lighten($subthemecolor, 70%);
-$active-nav-tabs-bgcolor: white;
 
 
 .growi:not(.login-page) {
 .growi:not(.login-page) {
   // add background-image
   // add background-image
@@ -42,15 +39,18 @@ $active-nav-tabs-bgcolor: white;
 //
 //
 html[light],
 html[light],
 html[dark] {
 html[dark] {
+  $primary: #d3c665;
   // Background colors
   // Background colors
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
+  $bgcolor-inline-code: #f0f0f0; //optional
 
 
   // Font colors
   // Font colors
-  $color-global: $subthemecolor;
-  $color-reversal: #eeeeee;
-  $color-link: lighten($color-global, 2%);
-  $color-link-hover: lighten($color-link, 20%);
+  $color-global: #112744;
+  $color-reversal: #eee;
+  $color-link: $subthemecolor;
+  $color-link-hover: lighten($color-link, 10%);
   $color-link-nabvar: $color-reversal;
   $color-link-nabvar: $color-reversal;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   $color-list: $color-global;
   $color-list: $color-global;
@@ -61,27 +61,39 @@ html[dark] {
 
 
   // Navbar
   // Navbar
   $bgcolor-navbar: $themecolor;
   $bgcolor-navbar: $themecolor;
+  $bgcolor-search-top-dropdown: $primary;
   $border-color-navbar-gradient-left: #545fff;
   $border-color-navbar-gradient-left: #545fff;
   $border-color-navbar-gradient-right: #00a6e5;
   $border-color-navbar-gradient-right: #00a6e5;
+  $border-image-navbar: linear-gradient(to right, #6458bc 33%, #5cb4ff 66%, #85d800 100%);
 
 
   // Logo colors
   // Logo colors
   $bgcolor-logo: $themecolor;
   $bgcolor-logo: $themecolor;
 
 
   // Sidebar
   // Sidebar
-  $bgcolor-sidebar: $themecolor;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($themecolor, 10%);
+  $bgcolor-sidebar: $subthemecolor;
+  $bgcolor-sidebar-nav-item-active: rgba(#000000, 0.37); // optional
+  $text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+  // Sidebar resize button
+  $color-resize-button: $color-reversal;
+  $bgcolor-resize-button: $primary;
+  $color-resize-button-hover: $color-reversal;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
+  $color-sidebar-context: $linktext;
+  $bgcolor-sidebar-context: #f4f6fc;
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #fafbff; // optional
 
 
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
-  $bgcolor-dropdown-link-active: $growi-blue;
-  $color-dropdown-link-active: $color-reversal;
-  $color-dropdown-link-hover: $color-global;
+  $bgcolor-dropdown-link-active: $primary;
+  $color-dropdown-link-active: $color-global;
+  $color-dropdown-link-hover: $color-reversal;
 
 
   // admin theme box
   // admin theme box
   $color-theme-color-box: lighten($themecolor, 20%);
   $color-theme-color-box: lighten($themecolor, 20%);
@@ -123,19 +135,6 @@ html[dark] {
     background-size: cover;
     background-size: cover;
   }
   }
 
 
-  /*
-  * Tabs
-  */
-  body:not(.on-edit) .nav.nav-tabs {
-    > li.active > a {
-      background: linear-gradient(
-        rgba($active-nav-tabs-bgcolor, 0) 0%,
-        rgba($active-nav-tabs-bgcolor, 0) 90%,
-        $active-nav-tabs-bgcolor 100%
-      ); // overwrite only the bottom pixel
-    }
-  }
-
   // login page
   // login page
   .nologin {
   .nologin {
     .input-group {
     .input-group {
@@ -192,28 +191,5 @@ html[dark] {
 
 
   .grw-navbar {
   .grw-navbar {
     background-image: url('/images/themes/christmas/christmas-navbar.jpg');
     background-image: url('/images/themes/christmas/christmas-navbar.jpg');
-    border-bottom: 4px solid $subthemecolor;
-  }
-
-  .grw-subnav {
-    background-color: #ffffff;
-  }
-
-  .nav-tabs {
-    border-bottom-color: $themecolor;
-  }
-
-  .nav-link {
-    border-color: $themecolor;
-  }
-
-  .nav-tabs .nav-link.active {
-    background: none;
-    border-color: $themecolor;
-  }
-
-  .search-top .dropdown-toggle {
-    color: black;
-    background-color: hsla(0, 0%, 100%, 0.8);
   }
   }
 }
 }

+ 34 - 6
src/client/styles/scss/theme/default.scss

@@ -19,7 +19,7 @@ html[light] {
 
 
   // Background colors
   // Background colors
   $bgcolor-global: white;
   $bgcolor-global: white;
-  $bgcolor-inline-code: #f9f2f4;
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
 
 
   // Font colors
   // Font colors
@@ -31,7 +31,7 @@ html[light] {
   $color-link-wiki: $color-link;
   $color-link-wiki: $color-link;
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-nabvar: #a7a7a7;
   $color-link-nabvar: #a7a7a7;
-  $color-inline-code: #c7254e;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   // $color-list: $color-global; // optional
   // $color-list: $color-global; // optional
@@ -40,6 +40,14 @@ html[light] {
   // $color-list-active: $color-reversal; // optional
   // $color-list-active: $color-reversal; // optional
   // $bgcolor-list-active: $primary; // optional
   // $bgcolor-list-active: $primary; // optional
 
 
+  // Table colors
+  // $bgcolor-subnabvar: #; // optional
+  // $color-table: #; // optional
+  // $bgcolor-table: #; // optional
+  // $border-color-table: #; // optional
+  // $color-table-hover: #; // optional
+  // $bgcolor-table-hover: #; // optional
+
   // Navbar
   // Navbar
   $bgcolor-navbar: #2a2929;
   $bgcolor-navbar: #2a2929;
   $bgcolor-search-top-dropdown: #209fd8;
   $bgcolor-search-top-dropdown: #209fd8;
@@ -67,11 +75,17 @@ html[light] {
   // Subnavigation
   // Subnavigation
   // $bgcolor-subnabvar: #fafafa; // optional
   // $bgcolor-subnabvar: #fafafa; // optional
 
 
+  // Tabs
+  // $color-nav-tabs-link-active: #; //optional
+  // $bordercolor-nav-tabs-hover: # # $bordercolor-nav-tabs; // optional
+  // $bordercolor-nav-tabs-active: # # $bgcolor-global; // optional
+
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
-  $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $border-color-theme: #ccc;
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;
@@ -98,7 +112,7 @@ html[dark] {
 
 
   // Background colors
   // Background colors
   $bgcolor-global: #131418;
   $bgcolor-global: #131418;
-  $bgcolor-inline-code: darken($bgcolor-global, 5%);
+  $bgcolor-inline-code: #1f1f22; //optional
   $bgcolor-card: darken($bgcolor-global, 5%);
   $bgcolor-card: darken($bgcolor-global, 5%);
 
 
   // Font colors
   // Font colors
@@ -110,7 +124,7 @@ html[dark] {
   $color-link-wiki: $color-link;
   $color-link-wiki: $color-link;
   $color-link-wiki-hover: lighten($color-link-wiki, 10%);
   $color-link-wiki-hover: lighten($color-link-wiki, 10%);
   $color-link-nabvar: #a7a7a7;
   $color-link-nabvar: #a7a7a7;
-  $color-inline-code: #c7254e;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   // $color-list: $color-global; // optional
   // $color-list: $color-global; // optional
@@ -119,6 +133,13 @@ html[dark] {
   $color-list-active: white; // optional
   $color-list-active: white; // optional
   // $bgcolor-list-active: $primary; // optional
   // $bgcolor-list-active: $primary; // optional
 
 
+  // Table colors
+  // $color-table: #; // optional
+  // $bgcolor-table: #; // optional
+  // $border-color-table: #; // optional
+  // $color-table-hover: #; // optional
+  // $bgcolor-table-hover: #; // optional
+
   // Navbar
   // Navbar
   $bgcolor-navbar: #2a2929;
   $bgcolor-navbar: #2a2929;
   $bgcolor-search-top-dropdown: $primary;
   $bgcolor-search-top-dropdown: $primary;
@@ -146,11 +167,18 @@ html[dark] {
   // Subnavigation
   // Subnavigation
   $bgcolor-subnabvar: lighten($bgcolor-global, 4%); // optional
   $bgcolor-subnabvar: lighten($bgcolor-global, 4%); // optional
 
 
+  // Tabs
+  $bordercolor-nav-tabs: #444; // optional
+  // $color-nav-tabs-link-active: #; //optional
+  $bordercolor-nav-tabs-hover: #666 #666 $bordercolor-nav-tabs; // optional
+  // $bordercolor-nav-tabs-active: # # $bgcolor-global; // optional
+
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
-  $border-color-theme: black; // former: `$navbar-border: #ccc;`
+  $border-color-theme: #444;
+  $bordercolor-inline-code: #666; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $primary;
   $bgcolor-dropdown-link-active: $primary;

+ 35 - 47
src/client/styles/scss/theme/future.scss

@@ -1,31 +1,28 @@
 @import '../variables';
 @import '../variables';
 @import '../override-bootstrap-variables';
 @import '../override-bootstrap-variables';
 
 
+$primary: #00b5b7;
 $themecolor: #16282d;
 $themecolor: #16282d;
-$themelight: rgba(11, 79, 104, 0.616);
-$accentcolor: #66eddf;
-
-$primary: $themelight;
-$dark: darken($themecolor, 5%);
+$accentcolor: #00fff5;
 
 
 html[light],
 html[light],
 html[dark] {
 html[dark] {
   // Background colors
   // Background colors
   $bgcolor-global: $themecolor;
   $bgcolor-global: $themecolor;
-  $bgcolor-inline-code: darken($themecolor, 5%);
+  $bgcolor-inline-code: #1f1f22; //optional
   $bgcolor-card: darken($themecolor, 5%);
   $bgcolor-card: darken($themecolor, 5%);
 
 
   // Font colors
   // Font colors
-  $color-global: lighten($themecolor, 35%);
-  $color-reversal: #eeeeee;
-  $color-header: #d9a364;
-  $color-link: lighten($primary, 20%);
+  $color-global: #95abba;
+  $color-reversal: $accentcolor;
+  $color-header: #95abba;
+  $color-link: $accentcolor;
   $color-link-hover: lighten($color-link, 20%);
   $color-link-hover: lighten($color-link, 20%);
-  $color-link-wiki: darken($themecolor, 5%);
+  $color-link-wiki: $accentcolor;
   $color-link-wiki-hover: darken($color-link-wiki, 5%);
   $color-link-wiki-hover: darken($color-link-wiki, 5%);
-  $color-link-nabvar: $color-reversal;
-  $color-inline-code: #c7254e;
-  $color-search: #050a0b;
+  $color-link-nabvar: #a7a7a7;
+  $color-inline-code: #c7254e; // optional
+  $color-search: $primary;
 
 
   // List Group colors
   // List Group colors
   $color-list: $color-global;
   $color-list: $color-global;
@@ -35,24 +32,38 @@ html[dark] {
   $color-list-hover: $color-reversal;
   $color-list-hover: $color-reversal;
 
 
   // Navbar
   // Navbar
-  $bgcolor-navbar: #011414;
-  $border-color-navbar-gradient-left: #545fff;
-  $border-color-navbar-gradient-right: #00a6e5;
+  $bgcolor-navbar: #01181a;
+  $bgcolor-search-top-dropdown: #00c2c4;
+  $border-image-navbar: linear-gradient(90deg, #6cfff9 0%, #0034c1 45%, #6cfff9 100%);
 
 
   // Logo colors
   // Logo colors
   $bgcolor-logo: darken($themecolor, 10%);
   $bgcolor-logo: darken($themecolor, 10%);
-  $fillcolor-logo-mark: lighten($accentcolor, 15%);
+  $fillcolor-logo-mark: #dedede;
 
 
   // Sidebar
   // Sidebar
-  $bgcolor-sidebar: $bgcolor-navbar;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-navbar, 10%);
+  $bgcolor-sidebar: #052e2f;
+  $bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
+  $text-shadow-sidebar-nav-item-active: 0px 0px 10px #969494; // optional
+
+  // Sidebar contents
+  $color-sidebar-context: #00c2c4;
+  $bgcolor-sidebar-context: #020b0b;
+
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #162126; // optional
+
+  // Sidebar resize button
+  $color-resize-button: #0E2329;
+  $bgcolor-resize-button: #00C2C4;
+  $color-resize-button-hover: #0E2329;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
 
 
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
   $border-color-theme: #407483;
   $border-color-theme: #407483;
+  $bordercolor-inline-code: #4d4d4d; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $primary;
   $bgcolor-dropdown-link-active: $primary;
@@ -78,31 +89,8 @@ html[dark] {
     }
     }
   }
   }
 
 
-  // Navs {
-  .nav-tabs {
-    border-bottom: $border-color-theme 1px solid;
-    .nav-link {
-      &:hover {
-        border-color: darken($border-color-theme, 10%);
-        border-bottom: none;
-      }
-      &.active {
-        color: $color-link;
-        background-color: transparent;
-        border-color: $border-color-theme;
-      }
-    }
-  }
-
-  // Search Top
-  .search-top {
-    .input-group-prepend .dropdown-toggle {
-      color: #5193a5;
-      background-color: $color-search;
-      border-color: $color-search;
-      &:hover {
-        background-color: darken($color-search, 10%);
-      }
-    }
+  pre {
+    color: #95abba;
+    background-color: #1f1f22;
   }
   }
 }
 }

+ 35 - 32
src/client/styles/scss/theme/halloween.scss

@@ -23,6 +23,7 @@ $light: lighten($secondary, 10%);
   #wrapper > .navbar {
   #wrapper > .navbar {
     background-image: url(/images/themes/halloween/halloween-navbar.jpg);
     background-image: url(/images/themes/halloween/halloween-navbar.jpg);
   }
   }
+
   // add background-image
   // add background-image
   #page-wrapper,
   #page-wrapper,
   .page-editor-preview-container {
   .page-editor-preview-container {
@@ -36,46 +37,63 @@ html[light],
 html[dark] {
 html[dark] {
   // Background colors
   // Background colors
   $bgcolor-global: #050000;
   $bgcolor-global: #050000;
-  $bgcolor-inline-code: #f9f2f4;
+  $bgcolor-inline-code: #1f1f22; //optional
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
 
 
   // Font colors
   // Font colors
   $color-global: #e9af2b;
   $color-global: #e9af2b;
   $color-reversal: #eeeeee;
   $color-reversal: #eeeeee;
   // $color-header: #2b2b2b;
   // $color-header: #2b2b2b;
-  $color-link: lighten($primary, 20%);
+  $color-link: #aa97cb;
   $color-link-hover: lighten($color-link, 20%);
   $color-link-hover: lighten($color-link, 20%);
-  $color-link-wiki: lighten($primary, 20%);
+  $color-link-wiki: #aa97cb;
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
-  $color-link-nabvar: $color-reversal;
-  $color-inline-code: #c7254e;
+  $color-link-nabvar: #a7a7a7;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
-  $color-list: $color-global;
+  $color-list: #979797;
   $bgcolor-list: transparent;
   $bgcolor-list: transparent;
   $color-list-active: $color-reversal;
   $color-list-active: $color-reversal;
   $bgcolor-list-active: $primary;
   $bgcolor-list-active: $primary;
   $color-list-hover: $themecolor;
   $color-list-hover: $themecolor;
 
 
+  // Search Top
+  $color-search: $primary;
+
   // Navbar
   // Navbar
-  $bgcolor-navbar: #223344;
-  $border-color-navbar-gradient-left: #545fff;
-  $border-color-navbar-gradient-right: #00a6e5;
+  $bgcolor-navbar: #eceded;
+  $bgcolor-search-top-dropdown: $primary;
+  $border-image-navbar: linear-gradient(90deg, #e3b7ff 0%, #134774 100%);
 
 
   // Logo colors
   // Logo colors
   $bgcolor-logo: darken($themecolor, 10%);
   $bgcolor-logo: darken($themecolor, 10%);
-  $fillcolor-logo-mark: lighten($accentcolor, 15%);
+  $fillcolor-logo-mark: #dedede;
 
 
   // Sidebar
   // Sidebar
-  $bgcolor-sidebar: $bgcolor-navbar;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-navbar, 10%);
+  $bgcolor-sidebar: #162b33;
+  $bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
+  $text-shadow-sidebar-nav-item-active: 0px 0px 10px #969494; // optional
+
+  // Sidebar contents
+  $color-sidebar-context: #aa97cb;
+  $bgcolor-sidebar-context: #1d2126;
+
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #2c2926; // optional
+
+  // Sidebar resize button
+  $color-resize-button: #effcfa;
+  $bgcolor-resize-button: $primary;
+  $color-resize-button-hover: #effcfa;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
 
 
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $bordercolor-inline-code: #4d4d4d; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $primary;
   $bgcolor-dropdown-link-active: $primary;
@@ -98,25 +116,10 @@ html[dark] {
   .table {
   .table {
     color: $color-global;
     color: $color-global;
   }
   }
-  .table-bordered {
-    th,
-    td {
-      border: 1px solid $themecolor;
-    }
-  }
 
 
-  // Nav
-  .nav-tabs {
-    border-bottom: $bordercolor 1px solid;
-    .nav-link {
-      &:hover {
-        border: $bordercolor 1px solid;
-      }
-      &.active {
-        color: lighten($themecolor, 5%);
-        background-color: transparent;
-        border: $bordercolor 1px solid;
-      }
-    }
+  pre {
+    color: #edba4a;
+    background: #000000;
   }
   }
+
 }
 }

+ 3 - 0
src/client/styles/scss/theme/island.scss

@@ -19,12 +19,14 @@ html[dark] {
   // Background colors
   // Background colors
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
   $bgcolor-global: lighten($color-themelight, 10%);
   $bgcolor-global: lighten($color-themelight, 10%);
+  $bgcolor-inline-code: #f0f0f0; //optional
 
 
   // Font colors
   // Font colors
   $color-reversal: #eeeeee;
   $color-reversal: #eeeeee;
   $color-link: lighten($color-global, 20%);
   $color-link: lighten($color-global, 20%);
   $color-link-hover: lighten($color-link, 20%);
   $color-link-hover: lighten($color-link, 20%);
   $color-link-nabvar: $color-reversal;
   $color-link-nabvar: $color-reversal;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   $color-list: $color-global;
   $color-list: $color-global;
@@ -52,6 +54,7 @@ html[dark] {
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc;
   $border-color-theme: #ccc;
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;

+ 16 - 67
src/client/styles/scss/theme/kibela.scss

@@ -7,7 +7,8 @@ $subthemecolor: rgb(88, 130, 250);
 $lightthemecolor: rgba(181, 203, 247, 0.61);
 $lightthemecolor: rgba(181, 203, 247, 0.61);
 
 
 // Light Mode
 // Light Mode
-html[light] {
+html[light],
+html[dark] {
   // Background colors
   // Background colors
   $bgcolor-navbar: white;
   $bgcolor-navbar: white;
   $bgcolor-navbar-active: $bgcolor-theme;
   $bgcolor-navbar-active: $bgcolor-theme;
@@ -31,71 +32,8 @@ html[light] {
   $bgcolor-list-active: $primary;
   $bgcolor-list-active: $primary;
   $color-list-hover: $color-reversal;
   $color-list-hover: $color-reversal;
 
 
-  // Logo colors
-  $bgcolor-logo: transparent;
-  $fillcolor-logo-mark: lighten($bgcolor-theme, 20%);
-
-  // Icon colors
-  $color-editor-icons: $color-global;
-
-  $color-link-wiki: lighten($bgcolor-theme, 20%);
-  $color-link-wiki-hover: lighten($color-link-wiki, 20%);
-  $color-link-nabvar: $color-global;
-  $color-link-nabvar-hover: $color-global;
-  $color-inline-code: $subthemecolor;
-
-  // border colors
-  $border-color-theme: $lightthemecolor;
-  $thickborder: #5584e1;
-
-  // dropdown colors
-  $bgcolor-dropdown-link-active: $growi-blue;
-  $color-dropdown-link-active: $color-reversal;
-  $color-dropdown-link-hover: $color-global;
-
-  // admin theme box
-  $color-theme-color-box: lighten($bgcolor-theme, 20%);
-
-  // alert
-  $color-alert: $color-reversal;
-
-  // badge
-  $color-badge: $color-reversal;
-
-  // Sidebar
-  $bgcolor-sidebar: $bgcolor-theme;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-theme, 10%);
-
-  @import 'apply-colors';
-  @import 'apply-colors-light';
-  @import 'apply-colors-kibela';
-}
-
-// Dark Mode ( same as Light Mode )
-html[dark] {
-  // Background colors
-  $bgcolor-navbar: white;
-  $bgcolor-navbar-active: $bgcolor-theme;
-  $bgcolor-global: $themelight;
-  $bgcolor-card: $lightthemecolor;
-  $bgcolor-inline-code: lighten($subthemecolor, 70%);
-  $color-header: $bgcolor-theme;
-  $color-global: #3c4a60;
-  $color-link: rgb(74, 109, 204);
-  $color-link-hover: lighten($color-link, 12%);
-  $sidebar-text: $bgcolor-theme;
-  $color-reversal: #eee;
-
-  $primary: $bgcolor-theme;
-  $info: lighten($bgcolor-theme, 20%);
-
-  // List Group colors
-  $color-list: $color-global;
-  $bgcolor-list: $bgcolor-global;
-  $color-list-active: $color-reversal;
-  $bgcolor-list-active: $primary;
-  $color-list-hover: $color-reversal;
+  // navbar
+  $bgcolor-search-top-dropdown: $primary;
 
 
   // Logo colors
   // Logo colors
   $bgcolor-logo: transparent;
   $bgcolor-logo: transparent;
@@ -113,6 +51,7 @@ html[dark] {
   // border colors
   // border colors
   $border-color-theme: $lightthemecolor;
   $border-color-theme: $lightthemecolor;
   $thickborder: #5584e1;
   $thickborder: #5584e1;
+  $bordercolor-inline-code: $lightthemecolor;
 
 
   // dropdown colors
   // dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;
@@ -131,7 +70,17 @@ html[dark] {
   // Sidebar
   // Sidebar
   $bgcolor-sidebar: $bgcolor-theme;
   $bgcolor-sidebar: $bgcolor-theme;
   $color-sidebar-context: $color-reversal;
   $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-theme, 5%);
+  $bgcolor-sidebar-context: lighten($bgcolor-theme, 10%);
+  // Sidebar resize button
+  $color-resize-button: $color-reversal;
+  $bgcolor-resize-button: #209fd8;
+  $color-resize-button-hover: $color-reversal;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
+  // Sidebar contents
+  $color-sidebar-context: $color-global;
+  $bgcolor-sidebar-context: #f4f6fc;
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #fafbff; // optional
 
 
   @import 'apply-colors';
   @import 'apply-colors';
   @import 'apply-colors-light';
   @import 'apply-colors-light';

+ 34 - 0
src/client/styles/scss/theme/mixins/_tables.scss

@@ -0,0 +1,34 @@
+//== Table
+// $table-variants: (
+//   'light': $light,
+//   'dark': $dark,
+// );
+
+// remove when master version is released
+// show https://github.com/twbs/bootstrap/blob/28cb1ff2b23253293601c51aff434c39b461025e/scss/mixins/_table-variants.scss
+// @mixin table-variant($state, $background) {
+//   .table-#{$state} {
+//     $table-hover-bg-factor: 0.075 !default;
+//     $table-striped-bg-factor: 0.05 !default;
+//     $body-bg: $white !default;
+//     $table-active-bg-factor: 0.1 !default;
+//     $table-border-factor: 0.1 !default;
+
+//     $color: color-contrast(mix(rgba($background, 1), $body-bg, opacity($background) * 100));
+//     $color: gray;
+//     $hover-bg: mix($color, $background, percentage($table-hover-bg-factor));
+//     $striped-bg: mix($color, $background, percentage($table-striped-bg-factor));
+//     $active-bg: mix($color, $background, percentage($table-active-bg-factor));
+
+//     --bs-table-bg: #{$background};
+//     --bs-table-striped-bg: #{$striped-bg};
+//     --bs-table-striped-color: #{color-contrast($striped-bg)};
+//     --bs-table-active-bg: #{$active-bg};
+//     --bs-table-active-color: #{color-contrast($active-bg)};
+//     --bs-table-hover-bg: #{$hover-bg};
+//     --bs-table-hover-color: #{color-contrast($hover-bg)};
+
+//     color: $color;
+//     border-color: mix($color, $background, percentage($table-border-factor));
+//   }
+// }

+ 6 - 3
src/client/styles/scss/theme/mono-blue.scss

@@ -12,7 +12,7 @@ html[light] {
 
 
   // Background colors
   // Background colors
   $bgcolor-global: $themelight;
   $bgcolor-global: $themelight;
-  $bgcolor-inline-code: lighten($subthemecolor, 70%);
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: darken($themelight, 5%);
   $bgcolor-card: darken($themelight, 5%);
 
 
   // Font colors
   // Font colors
@@ -23,7 +23,7 @@ html[light] {
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-nabvar: $color-reversal;
   $color-link-nabvar: $color-reversal;
-  $color-inline-code: $subthemecolor;
+  $color-inline-code: #c7254e; // optional
   $color-search: #c0d6df;
   $color-search: #c0d6df;
 
 
   // List Group colors
   // List Group colors
@@ -62,6 +62,7 @@ html[light] {
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc;
   $border-color-theme: #ccc;
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $primary;
   $bgcolor-dropdown-link-active: $primary;
@@ -107,7 +108,7 @@ html[dark] {
   // Background colors
   // Background colors
   $bgcolor-global: $themedark;
   $bgcolor-global: $themedark;
   $bgcolor-navbar: #27343b;
   $bgcolor-navbar: #27343b;
-  $bgcolor-inline-code: #0a121b;
+  $bgcolor-inline-code: #1f1f22; //optional
   $bgcolor-card: darken($themedark, 5%);
   $bgcolor-card: darken($themedark, 5%);
 
 
   // Font colors
   // Font colors
@@ -119,6 +120,7 @@ html[dark] {
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-nabvar: $color-reversal;
   $color-link-nabvar: $color-reversal;
   $color-inline-code: $subthemecolor;
   $color-inline-code: $subthemecolor;
+  $color-inline-code: #c7254e; // optional
   $color-search: #000102;
   $color-search: #000102;
 
 
   // List Group colors
   // List Group colors
@@ -158,6 +160,7 @@ html[dark] {
 
 
   // Border colors
   // Border colors
   $border-color-theme: #146aa0;
   $border-color-theme: #146aa0;
+  $bordercolor-inline-code: #4d4d4d; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $primary;
   $bgcolor-dropdown-link-active: $primary;

+ 7 - 6
src/client/styles/scss/theme/nature.scss

@@ -39,13 +39,13 @@ html[light],
 html[dark] {
 html[dark] {
   $primary: #460039;
   $primary: #460039;
   $light: #f0f0f0;
   $light: #f0f0f0;
-  
+
   // Background colors
   // Background colors
   $bgcolor-global: #fdfdfd;
   $bgcolor-global: #fdfdfd;
-  $bgcolor-inline-code: #eaeaea;
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: #f1ffe4;
   $bgcolor-card: #f1ffe4;
   $bgcolor-subnabvar: #fafafa;
   $bgcolor-subnabvar: #fafafa;
-  
+
   // Font colors
   // Font colors
   $color-global: #460039;
   $color-global: #460039;
   $color-reversal: #eeeeee;
   $color-reversal: #eeeeee;
@@ -54,14 +54,14 @@ html[dark] {
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki: lighten($primary, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-wiki-hover: lighten($color-link-wiki, 20%);
   $color-link-nabvar: #a7a7a7;
   $color-link-nabvar: #a7a7a7;
-  $color-inline-code: #890000;
+  $color-inline-code: #c7254e; // optional
   $color-search: white;
   $color-search: white;
-  
+
   // Navbar
   // Navbar
   $bgcolor-navbar: #234136;
   $bgcolor-navbar: #234136;
   $bgcolor-search-top-dropdown: $themecolor;
   $bgcolor-search-top-dropdown: $themecolor;
   $border-image-navbar: linear-gradient(to right, #5c78ef 0%, #16bc42 50%, #5c78ef 100%);
   $border-image-navbar: linear-gradient(to right, #5c78ef 0%, #16bc42 50%, #5c78ef 100%);
-  
+
   // Logo colors
   // Logo colors
   $bgcolor-logo: $bgcolor-navbar;
   $bgcolor-logo: $bgcolor-navbar;
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
@@ -80,6 +80,7 @@ html[dark] {
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc;
   $border-color-theme: #ccc;
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;

+ 21 - 12
src/client/styles/scss/theme/spring.scss

@@ -48,22 +48,22 @@ $accentcolor: #e08dbc;
 html[light],
 html[light],
 html[dark] {
 html[dark] {
   $primary: $themecolor;
   $primary: $themecolor;
+  $secondary: $accentcolor;
 
 
   // Background colors
   // Background colors
   $bgcolor-global: white;
   $bgcolor-global: white;
-  $bgcolor-inline-code: #f9f2f4;
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: #f5f5f5;
   $bgcolor-card: #f5f5f5;
 
 
   // Font colors
   // Font colors
   $color-global: black;
   $color-global: black;
   $color-reversal: white;
   $color-reversal: white;
-  // $color-header: #2b2b2b;
-  $color-link: lighten($color-global, 20%);
-  $color-link-hover: $subthemecolor;
+  $color-link: $subthemecolor;
+  $color-link-hover: lighten($subthemecolor, 10%);
   $color-link-wiki: $subthemecolor;
   $color-link-wiki: $subthemecolor;
-  $color-link-wiki-hover: lighten($color-link-wiki, 20%);
+  $color-link-wiki-hover: lighten($color-link-wiki, 10%);
   $color-link-nabvar: $bgcolor-global;
   $color-link-nabvar: $bgcolor-global;
-  $color-inline-code: #c7254e;
+  $color-inline-code: #c7254e; // optional
 
 
   // List Group colors
   // List Group colors
   $color-list: $color-global;
   $color-list: $color-global;
@@ -73,24 +73,33 @@ html[dark] {
   $color-list-hover: lighten($accentcolor, 20%);
   $color-list-hover: lighten($accentcolor, 20%);
 
 
   // Navbar
   // Navbar
-  $bgcolor-navbar: $themecolor;
-  $border-color-navbar-gradient-left: #545fff;
-  $border-color-navbar-gradient-right: #00a6e5;
+  $bgcolor-navbar: #d3687c;
+  $bgcolor-search-top-dropdown: $themecolor;
+  $border-image-navbar: linear-gradient(to right, #cbe682 0%, #4ad6e8 50%, #ea42f0 100%);
 
 
   // Logo colors
   // Logo colors
   $bgcolor-logo: $bgcolor-navbar;
   $bgcolor-logo: $bgcolor-navbar;
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
   $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
 
 
   // Sidebar
   // Sidebar
-  $bgcolor-sidebar: $bgcolor-navbar;
-  $color-sidebar-context: $color-reversal;
-  $bgcolor-sidebar-context: lighten($bgcolor-navbar, 10%);
+  $bgcolor-sidebar: $themecolor;
+  // Sidebar resize button
+  $color-resize-button: $color-reversal;
+  $bgcolor-resize-button: $subthemecolor;
+  $color-resize-button-hover: $color-reversal;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
+  // Sidebar contents
+  $color-sidebar-context: $subthemecolor;
+  $bgcolor-sidebar-context: #f4f6fc;
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: #fafbff; // optional
 
 
   // Icon colors
   // Icon colors
   $color-editor-icons: $color-global;
   $color-editor-icons: $color-global;
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;

+ 4 - 3
src/client/styles/scss/theme/wood.scss

@@ -42,7 +42,7 @@ html[dark] {
 
 
   // Background colors
   // Background colors
   $bgcolor-global: #ffffff;
   $bgcolor-global: #ffffff;
-  $bgcolor-inline-code: #eaeaea;
+  $bgcolor-inline-code: #f0f0f0; //optional
   $bgcolor-card: #ece8de;
   $bgcolor-card: #ece8de;
 
 
   // Font colors
   // Font colors
@@ -54,7 +54,7 @@ html[dark] {
   $color-link-wiki: lighten($themecolor, 5%);
   $color-link-wiki: lighten($themecolor, 5%);
   $color-link-wiki-hover: lighten($color-link-wiki, 15%);
   $color-link-wiki-hover: lighten($color-link-wiki, 15%);
   $color-link-nabvar: #a7a7a7;
   $color-link-nabvar: #a7a7a7;
-  $color-inline-code: #890000;
+  $color-inline-code: #c7254e; // optional
   $color-search: white;
   $color-search: white;
 
 
   // List Group colors
   // List Group colors
@@ -83,6 +83,7 @@ html[dark] {
 
 
   // Border colors
   // Border colors
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
   $border-color-theme: #ccc; // former: `$navbar-border: #ccc;`
+  $bordercolor-inline-code: #ccc8c8; // optional
 
 
   // Dropdown colors
   // Dropdown colors
   $bgcolor-dropdown-link-active: $growi-blue;
   $bgcolor-dropdown-link-active: $growi-blue;
@@ -123,7 +124,7 @@ html[dark] {
   }
   }
 
 
   // Sidebar
   // Sidebar
-  .grw-sidebar div[data-testid='GlobalNavigation']{
+  .grw-sidebar div[data-testid='GlobalNavigation'] {
     * {
     * {
       background-image: url('/images/themes/wood/wood-navbar.jpg');
       background-image: url('/images/themes/wood/wood-navbar.jpg');
     }
     }

+ 4 - 2
src/lib/models/devided-page-path.js

@@ -1,11 +1,11 @@
-import { pathUtils } from 'growi-commons';
+const { pathUtils } = require('growi-commons');
 
 
 // https://regex101.com/r/BahpKX/2
 // https://regex101.com/r/BahpKX/2
 const PATTERN_INCLUDE_DATE = /^(.+\/[^/]+)\/(\d{4}|\d{4}\/\d{2}|\d{4}\/\d{2}\/\d{2})$/;
 const PATTERN_INCLUDE_DATE = /^(.+\/[^/]+)\/(\d{4}|\d{4}\/\d{2}|\d{4}\/\d{2}\/\d{2})$/;
 // https://regex101.com/r/WVpPpY/1
 // https://regex101.com/r/WVpPpY/1
 const PATTERN_DEFAULT = /^((.*)\/)?([^/]+)$/;
 const PATTERN_DEFAULT = /^((.*)\/)?([^/]+)$/;
 
 
-export default class DevidedPagePath {
+class DevidedPagePath {
 
 
   constructor(path, skipNormalize = false, evalDatePath = false) {
   constructor(path, skipNormalize = false, evalDatePath = false) {
 
 
@@ -43,3 +43,5 @@ export default class DevidedPagePath {
   }
   }
 
 
 }
 }
+
+module.exports = DevidedPagePath;

+ 6 - 4
src/lib/models/linked-page-path.js

@@ -1,12 +1,12 @@
-import { pathUtils } from 'growi-commons';
-import { isTrashPage } from '@commons/util/path-utils';
+const { pathUtils } = require('growi-commons');
+const { isTrashPage } = require('@commons/util/path-utils');
 
 
-import DevidedPagePath from './devided-page-path';
+const DevidedPagePath = require('./devided-page-path');
 
 
 /**
 /**
  * Linked Array Structured PagePath Model
  * Linked Array Structured PagePath Model
  */
  */
-export default class LinkedPagePath {
+class LinkedPagePath {
 
 
   constructor(path, skipNormalize = false) {
   constructor(path, skipNormalize = false) {
 
 
@@ -34,3 +34,5 @@ export default class LinkedPagePath {
   }
   }
 
 
 }
 }
+
+module.exports = LinkedPagePath;

+ 2 - 2
src/server/models/user.js

@@ -255,10 +255,10 @@ module.exports = function(crowi) {
       const hash = md5(email.trim().toLowerCase());
       const hash = md5(email.trim().toLowerCase());
       return `https://gravatar.com/avatar/${hash}`;
       return `https://gravatar.com/avatar/${hash}`;
     }
     }
-    if (this.image) {
+    if (this.image != null) {
       return this.image;
       return this.image;
     }
     }
-    if (this.imageAttachment) {
+    if (this.imageAttachment != null && this.imageAttachment._id != null) {
       const Attachment = crowi.model('Attachment');
       const Attachment = crowi.model('Attachment');
       const imageAttachment = await Attachment.findById(this.imageAttachment);
       const imageAttachment = await Attachment.findById(this.imageAttachment);
       return imageAttachment.filePathProxied;
       return imageAttachment.filePathProxied;

+ 1 - 3
src/server/routes/apiv3/users.js

@@ -585,13 +585,11 @@ module.exports = (crowi) => {
         };
         };
       }));
       }));
 
 
-      let updatedUsers = [];
       if (requests.length > 0) {
       if (requests.length > 0) {
         await User.bulkWrite(requests);
         await User.bulkWrite(requests);
-        updatedUsers = await User.find({ _id: { $in: userIds } }, User.USER_PUBLIC_FIELDS);
       }
       }
 
 
-      return res.apiv3({ updatedUsers });
+      return res.apiv3({});
     }
     }
     catch (err) {
     catch (err) {
       logger.error('Error', err);
       logger.error('Error', err);

+ 1 - 1
src/server/routes/installer.js

@@ -38,7 +38,7 @@ module.exports = function(crowi, app) {
 
 
     // create /Sandbox/*
     // create /Sandbox/*
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox.md'), '/Sandbox', owner, lang));
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox.md'), '/Sandbox', owner, lang));
-    promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-bootstrap4.md'), '/Sandbox/Bootstrap3', owner, lang));
+    promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-bootstrap4.md'), '/Sandbox/Bootstrap4', owner, lang));
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-diagrams.md'), '/Sandbox/Diagrams', owner, lang));
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-diagrams.md'), '/Sandbox/Diagrams', owner, lang));
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-math.md'), '/Sandbox/Math', owner, lang));
     promises.push(createPage(path.join(crowi.localeDir, lang, 'sandbox-math.md'), '/Sandbox/Math', owner, lang));
 
 

+ 22 - 4
src/server/service/customize.js

@@ -1,4 +1,7 @@
-const logger = require('@alias/logger')('growi:service:CustomizeService'); // eslint-disable-line no-unused-vars
+// eslint-disable-next-line no-unused-vars
+const logger = require('@alias/logger')('growi:service:CustomizeService');
+
+const DevidedPagePath = require('@commons/models/devided-page-path');
 
 
 /**
 /**
  * the service class of CustomizeService
  * the service class of CustomizeService
@@ -35,17 +38,32 @@ class CustomizeService {
     let configValue = this.configManager.getConfig('crowi', 'customize:title');
     let configValue = this.configManager.getConfig('crowi', 'customize:title');
 
 
     if (configValue == null || configValue.trim().length === 0) {
     if (configValue == null || configValue.trim().length === 0) {
-      configValue = '{{page}} - {{sitename}}';
+      configValue = '{{pagename}} - {{sitename}}';
     }
     }
 
 
     this.customTitleTemplate = configValue;
     this.customTitleTemplate = configValue;
   }
   }
 
 
-  generateCustomTitle(page) {
+  generateCustomTitle(pageOrPath) {
+    const path = pageOrPath.path || pageOrPath;
+    const dPagePath = new DevidedPagePath(path, true, true);
+
+    const customTitle = this.customTitleTemplate
+      .replace('{{sitename}}', this.appService.getAppTitle())
+      .replace('{{pagepath}}', path)
+      .replace('{{page}}', dPagePath.latter) // for backward compatibility
+      .replace('{{pagename}}', dPagePath.latter);
+
+    return this.xssService.process(customTitle);
+  }
+
+  generateCustomTitleForFixedPageName(title) {
     // replace
     // replace
     const customTitle = this.customTitleTemplate
     const customTitle = this.customTitleTemplate
       .replace('{{sitename}}', this.appService.getAppTitle())
       .replace('{{sitename}}', this.appService.getAppTitle())
-      .replace('{{page}}', page);
+      .replace('{{page}}', title)
+      .replace('{{pagepath}}', title)
+      .replace('{{pagename}}', title);
 
 
     return this.xssService.process(customTitle);
     return this.xssService.process(customTitle);
   }
   }

+ 1 - 1
src/server/service/passport.js

@@ -854,7 +854,7 @@ class PassportService {
         if (user == null) {
         if (user == null) {
           throw new Error('user not found');
           throw new Error('user not found');
         }
         }
-        if (!user.imageUrlCached) {
+        if (user.imageUrlCached == null) {
           await user.updateImageUrlCached();
           await user.updateImageUrlCached();
           await user.save();
           await user.save();
         }
         }

+ 1 - 1
src/server/views/admin/app.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('App Settings')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('App Settings')) }}{% endblock %}
 
 
 {% block head_warn_alert_siteurl_undefined %} {# remove including block for './widget/alert_siteurl_undefined.html' #}
 {% block head_warn_alert_siteurl_undefined %} {# remove including block for './widget/alert_siteurl_undefined.html' #}
 {% endblock %}
 {% endblock %}

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

@@ -1,5 +1,5 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Customize')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Customize')) }}{% endblock %}
 
 
 {% block html_additional_headers %}
 {% block html_additional_headers %}
 {% parent %}
 {% parent %}
@@ -19,6 +19,9 @@
 {% block content_main %}
 {% block content_main %}
 <div class="content-main admin-customize row">
 <div class="content-main admin-customize row">
   {% parent %}
   {% parent %}
+  <div id="grw-hljs-container-for-demo">
+    {{ cdnHighlightJsStyleTag(getConfig('crowi', 'customize:highlightJsStyle')) }}
+  </div>
   <div class="col-lg-9" id="admin-customize"></div>
   <div class="col-lg-9" id="admin-customize"></div>
 </div>
 </div>
 {% endblock content_main %}
 {% endblock content_main %}

+ 1 - 1
src/server/views/admin/export.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Export Archive Data')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Export Archive Data')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Export Archive Data') }}</h1>
 <h1 class="title">{{ t('Export Archive Data') }}</h1>

+ 1 - 1
src/server/views/admin/external-accounts.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('external_account_management')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('external_account_management')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('User_Management') }} / {{ t('external_account_management') }}</h1>
 <h1 class="title">{{ t('User_Management') }} / {{ t('external_account_management') }}</h1>

+ 1 - 1
src/server/views/admin/global-notification-detail.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Notification Settings')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Notification Settings')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Notification Settings') }}</h1>
 <h1 class="title">{{ t('Notification Settings') }}</h1>

+ 1 - 1
src/server/views/admin/importer.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Import Data')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Import Data')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Import Data') }}</h1>
 <h1 class="title">{{ t('Import Data') }}</h1>

+ 1 - 1
src/server/views/admin/index.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Wiki Management Home Page')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Wiki Management Home Page')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title"> {{ t('Wiki Management Home Page') }}</h1>
 <h1 class="title"> {{ t('Wiki Management Home Page') }}</h1>

+ 1 - 1
src/server/views/admin/markdown.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Markdown Settings')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Markdown Settings')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Markdown Settings') }}</h1>
 <h1 class="title">{{ t('Markdown Settings') }}</h1>

+ 1 - 1
src/server/views/admin/notification.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Notification Settings')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Notification Settings')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Notification Settings') }}</h1>
 <h1 class="title">{{ t('Notification Settings') }}</h1>

+ 1 - 1
src/server/views/admin/search.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('Full Text Search Management')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Full Text Search Management')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('Full Text Search Management') }}</h1>
 <h1 class="title">{{ t('Full Text Search Management') }}</h1>

+ 1 - 1
src/server/views/admin/security.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('security_settings')) }} · {% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('security_settings')) }} · {% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('security_settings') }}</h1>
 <h1 class="title">{{ t('security_settings') }}</h1>

+ 1 - 1
src/server/views/admin/user-group-detail.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('UserGroup Management') + '/' + userGroup.name) | preventXss }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('UserGroup Management') + '/' + userGroup.name) | preventXss }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('UserGroup Management') + '/' + userGroup.name | preventXss }}</h1>
 <h1 class="title">{{ t('UserGroup Management') + '/' + userGroup.name | preventXss }}</h1>

+ 1 - 1
src/server/views/admin/user-groups.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('UserGroup Management')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('UserGroup Management')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('UserGroup Management') }}</h1>
 <h1 class="title">{{ t('UserGroup Management') }}</h1>

+ 1 - 1
src/server/views/admin/users.html

@@ -1,6 +1,6 @@
 {% extends '../layout/admin.html' %}
 {% extends '../layout/admin.html' %}
 
 
-{% block html_title %}{{ customizeService.generateCustomTitle(t('User_Management')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('User_Management')) }}{% endblock %}
 
 
 {% block content_header %}
 {% block content_header %}
 <h1 class="title">{{ t('User_Management') }}</h1>
 <h1 class="title">{{ t('User_Management') }}</h1>

+ 1 - 1
src/server/views/installer.html

@@ -4,7 +4,7 @@
 <head>
 <head>
   <meta charset="utf-8">
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-  <title>{{ customizeService.generateCustomTitle(t('installer.setup')) }}</title>
+  <title>{{ customizeService.generateCustomTitleForFixedPageName(t('installer.setup')) }}</title>
   <meta name="description" content="">
   <meta name="description" content="">
   <meta name="author" content="">
   <meta name="author" content="">
 
 

Неке датотеке нису приказане због велике количине промена