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

Merge branch 'master' into imprv/145476-146792-use-hashmark-for-link-icon

reiji-h 1 год назад
Родитель
Сommit
7750428a73
100 измененных файлов с 256 добавлено и 345 удалено
  1. 11 0
      .changeset/config.json
  2. 1 0
      .eslintrc.js
  3. 14 4
      .stylelintrc.json
  4. 18 1
      CHANGELOG.md
  5. 0 1
      apps/app/.eslintrc.js
  6. 1 2
      apps/app/.stylelintrc.json
  7. 1 1
      apps/app/docker/README.md
  8. 10 9
      apps/app/package.json
  9. 0 147
      apps/app/src/client/models/MarkdownTable.js
  10. 1 1
      apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts
  11. 3 1
      apps/app/src/components/Admin/App/MaskedInput.module.scss
  12. 1 0
      apps/app/src/components/Admin/UserManagement.module.scss
  13. 0 1
      apps/app/src/components/Common/CopyDropdown/CopyDropdown.module.scss
  14. 0 2
      apps/app/src/components/Common/DrawerToggler/DrawerToggler.module.scss
  15. 0 1
      apps/app/src/components/Common/PagePathNav/PagePathNav.module.scss
  16. 2 1
      apps/app/src/components/Common/PageViewLayout.module.scss
  17. 1 1
      apps/app/src/components/CustomNavigation/CustomNav.module.scss
  18. 2 2
      apps/app/src/components/DescendantsPageListModal.module.scss
  19. 4 0
      apps/app/src/components/ItemsTree/ItemsTree.module.scss
  20. 2 0
      apps/app/src/components/ItemsTree/ItemsTreeContentSkeleton.module.scss
  21. 3 1
      apps/app/src/components/Layout/Admin.module.scss
  22. 28 0
      apps/app/src/components/Layout/BasicLayout.module.scss
  23. 7 1
      apps/app/src/components/Layout/BasicLayout.tsx
  24. 15 11
      apps/app/src/components/Layout/NoLoginLayout.module.scss
  25. 2 3
      apps/app/src/components/LoginForm/LoginForm.module.scss
  26. 0 0
      apps/app/src/components/Me/ColorModeSettings.module.scss
  27. 0 2
      apps/app/src/components/Me/ColorModeSettings.tsx
  28. 1 1
      apps/app/src/components/Navbar/GrowiContextualSubNavigation.module.scss
  29. 1 0
      apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss
  30. 2 0
      apps/app/src/components/Navbar/PageEditorModeManager.module.scss
  31. 1 1
      apps/app/src/components/Page/markdown-table-util-for-view.ts
  32. 2 2
      apps/app/src/components/PageAccessoriesModal/PageAccessoriesModal.module.scss
  33. 5 6
      apps/app/src/components/PageComment/Comment.module.scss
  34. 1 2
      apps/app/src/components/PageComment/CommentEditor.module.scss
  35. 1 0
      apps/app/src/components/PageComment/CommentPreview.module.scss
  36. 1 0
      apps/app/src/components/PageComment/DeleteCommentModal.module.scss
  37. 1 0
      apps/app/src/components/PageComment/SwitchingButtonGroup.module.scss
  38. 3 3
      apps/app/src/components/PageComment/_comment-inheritance.scss
  39. 1 0
      apps/app/src/components/PageContentFooter.module.scss
  40. 2 2
      apps/app/src/components/PageControls/BookmarkButtons.module.scss
  41. 1 2
      apps/app/src/components/PageControls/LikeButtons.module.scss
  42. 0 2
      apps/app/src/components/PageControls/PageControls.module.scss
  43. 15 10
      apps/app/src/components/PageControls/PageControls.tsx
  44. 0 2
      apps/app/src/components/PageControls/SearchButton.module.scss
  45. 0 2
      apps/app/src/components/PageControls/SeenUserInfo.module.scss
  46. 0 2
      apps/app/src/components/PageControls/SubscribeButton.module.scss
  47. 0 3
      apps/app/src/components/PageCreateModal.module.scss
  48. 1 0
      apps/app/src/components/PageEditor/EditorNavbar/EditorNavbar.module.scss
  49. 1 1
      apps/app/src/components/PageEditor/EditorNavbarBottom.module.scss
  50. 5 4
      apps/app/src/components/PageEditor/GridEditModal.module.scss
  51. 1 1
      apps/app/src/components/PageEditor/HandsontableModal.module.scss
  52. 1 1
      apps/app/src/components/PageEditor/HandsontableModal.tsx
  53. 1 1
      apps/app/src/components/PageEditor/LinkEditModal.tsx
  54. 2 2
      apps/app/src/components/PageEditor/LinkEditPreview.module.scss
  55. 1 1
      apps/app/src/components/PageEditor/MarkdownTableDataImportForm.tsx
  56. 4 3
      apps/app/src/components/PageEditor/PageEditor.tsx
  57. 1 1
      apps/app/src/components/PageEditor/Preview.module.scss
  58. 1 2
      apps/app/src/components/PageEditor/markdown-table-util-for-editor.ts
  59. 1 0
      apps/app/src/components/PageHeader/PageHeader.module.scss
  60. 2 2
      apps/app/src/components/PagePresentationModal.module.scss
  61. 1 1
      apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss
  62. 1 0
      apps/app/src/components/PageSideContents/PageSideContents.module.scss
  63. 1 1
      apps/app/src/components/PageStatusAlert.module.scss
  64. 2 1
      apps/app/src/components/PageTags/TagLabels.module.scss
  65. 0 1
      apps/app/src/components/RevisionComparer/RevisionComparer.module.scss
  66. 0 1
      apps/app/src/components/SearchPage/SearchControl.module.scss
  67. 1 0
      apps/app/src/components/SearchPage/SearchResultContent.module.scss
  68. 1 0
      apps/app/src/components/SearchTypeahead.module.scss
  69. 9 5
      apps/app/src/components/ShortcutsModal.module.scss
  70. 1 3
      apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss
  71. 0 1
      apps/app/src/components/Sidebar/PageCreateButton/CreateButton.module.scss
  72. 2 6
      apps/app/src/components/Sidebar/PageCreateButton/DropendToggle.module.scss
  73. 0 2
      apps/app/src/components/Sidebar/PageCreateButton/PageCreateButton.module.scss
  74. 3 0
      apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.module.scss
  75. 2 2
      apps/app/src/components/Sidebar/ResizableArea/ResizableArea.module.scss
  76. 3 1
      apps/app/src/components/Sidebar/Sidebar.module.scss
  77. 0 1
      apps/app/src/components/Sidebar/SidebarContents.module.scss
  78. 1 0
      apps/app/src/components/Sidebar/SidebarHead/SidebarHead.module.scss
  79. 4 3
      apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.module.scss
  80. 2 0
      apps/app/src/components/Sidebar/SidebarNav/PersonalDropdown.module.scss
  81. 3 3
      apps/app/src/components/Sidebar/SidebarNav/PrimaryItems.module.scss
  82. 2 1
      apps/app/src/components/Sidebar/SidebarNav/SecondaryItems.module.scss
  83. 1 4
      apps/app/src/components/Sidebar/SidebarNav/SidebarNav.module.scss
  84. 0 1
      apps/app/src/components/Sidebar/SidebarNav/SkeletonItem.module.scss
  85. 2 0
      apps/app/src/components/Sidebar/Skeleton/DefaultContentSkelton.module.scss
  86. 0 2
      apps/app/src/components/Sidebar/_button-styles.scss
  87. 1 0
      apps/app/src/components/Skeleton.module.scss
  88. 1 4
      apps/app/src/components/StaffCredit/StaffCredit.module.scss
  89. 0 1
      apps/app/src/components/TableOfContents.module.scss
  90. 1 0
      apps/app/src/components/TagList.module.scss
  91. 3 25
      apps/app/src/components/UsersHomepageFooter.module.scss
  92. 0 1
      apps/app/src/components/UsersHomepageFooter.tsx
  93. 5 3
      apps/app/src/features/growi-plugin/client/components/Admin/PluginsExtensionPageContents/PluginCard.module.scss
  94. 0 1
      apps/app/src/features/search/client/components/SearchMenuItem.module.scss
  95. 6 0
      apps/app/src/linter-checker/.stylelintrc.json
  96. 1 1
      apps/app/src/linter-checker/test.scss
  97. 1 0
      apps/app/src/pages/login/index.module.scss
  98. 3 4
      apps/app/src/server/service/yjs-connection-manager.ts
  99. 1 2
      apps/app/src/stores/modal.tsx
  100. 4 11
      apps/app/src/styles/_editor.scss

+ 11 - 0
.changeset/config.json

@@ -0,0 +1,11 @@
+{
+  "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
+  "changelog": ["@changesets/changelog-github", { "repo": "weseek/growi" }],
+  "commit": false,
+  "fixed": [],
+  "linked": [],
+  "access": "restricted",
+  "baseBranch": "master",
+  "updateInternalDependencies": "patch",
+  "ignore": []
+}

+ 1 - 0
.eslintrc.js

@@ -48,6 +48,7 @@ module.exports = {
         'newlines-between': 'always',
       },
     ],
+    '@typescript-eslint/consistent-type-imports': 'warn',
     '@typescript-eslint/no-explicit-any': 'off',
     '@typescript-eslint/explicit-module-boundary-types': 'off',
     indent: [

+ 14 - 4
.stylelintrc.json

@@ -1,15 +1,25 @@
 {
   "extends": [
+    "stylelint-config-recommended-scss",
     "stylelint-config-recess-order"
   ],
   "rules": {
-    "indentation": 2,
-    "string-quotes": "single",
+    "no-duplicate-selectors": null,
+    "scss/comment-no-empty": null,
+    "scss/at-extend-no-missing-placeholder": null,
     "rule-empty-line-before": [ "always-multi-line", {
       "except": ["after-single-line-comment", "first-nested"],
       "ignore": ["after-comment", "inside-block"]
     } ],
-    "selector-combinator-space-before": "always",
-    "selector-combinator-space-after": "always"
+    "color-function-notation": "legacy",
+    "selector-pseudo-class-no-unknown": [
+      true,
+      {
+        "ignorePseudoClasses": [
+          "global",
+          "local"
+        ]
+      }
+    ]
   }
 }

+ 18 - 1
CHANGELOG.md

@@ -1,9 +1,26 @@
 # Changelog
 
-## [Unreleased](https://github.com/weseek/growi/compare/v7.0.6...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v7.0.7...HEAD)
 
 *Please do not manually update this file. We've automated the process.*
 
+## [v7.0.7](https://github.com/weseek/growi/compare/v7.0.6...v7.0.7) - 2024-05-27
+
+### 🚀 Improvement
+
+* imprv: Behavior of dropdown toggle in groundglassbar (#8832) @maeshinshin
+* imprv: toastr location (#8831) @yuki-takei
+
+### 🐛 Bug Fixes
+
+* fix: Do not insert initial value when input is empty in editor (#8773) @miya
+
+### 🧰 Maintenance
+
+* support: Apply changesets (#8840) @yuki-takei
+* support: Upgrade yjs packages (#8839) @yuki-takei
+* support: Upgrade stylelint (#8835) @yuki-takei
+
 ## [v7.0.6](https://github.com/weseek/growi/compare/v7.0.5...v7.0.6) - 2024-05-20
 
 ### 🐛 Bug Fixes

+ 0 - 1
apps/app/.eslintrc.js

@@ -27,7 +27,6 @@ module.exports = {
       },
     ]],
     '@typescript-eslint/no-var-requires': 'off',
-    '@typescript-eslint/consistent-type-imports': 'warn',
 
     // set 'warn' temporarily -- 2021.08.02 Yuki Takei
     '@typescript-eslint/no-use-before-define': ['warn'],

+ 1 - 2
apps/app/.stylelintrc.json

@@ -1,7 +1,6 @@
 {
   "extends": "../../.stylelintrc.json",
   "ignoreFiles": [
-    "src/styles/prebuilt/*.css",
-    "src/linter-checker/test.scss"
+    "src/styles/prebuilt/*.css"
   ]
 }

+ 1 - 1
apps/app/docker/README.md

@@ -10,7 +10,7 @@ GROWI Official docker image
 Supported tags and respective Dockerfile links
 ------------------------------------------------
 
-* [`7.0.6`, `7.0`, `7`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v7.0.6/apps/app/docker/Dockerfile)
+* [`7.0.7`, `7.0`, `7`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v7.0.7/apps/app/docker/Dockerfile)
 * [`6.3.2`, `6.3`, `6` (Dockerfile)](https://github.com/weseek/growi/blob/v6.3.2/apps/app/docker/Dockerfile)
 * [`6.2.4`, `6.2` (Dockerfile)](https://github.com/weseek/growi/blob/v6.2.4/apps/app/docker/Dockerfile)
 * [`6.1.15`, `6.1` (Dockerfile)](https://github.com/weseek/growi/blob/v6.1.15/apps/app/docker/Dockerfile)

+ 10 - 9
apps/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/app",
-  "version": "7.0.7-RC.0",
+  "version": "7.0.8-RC.0",
   "license": "MIT",
   "scripts": {
     "//// for production": "",
@@ -29,7 +29,7 @@
     "dev:ci": "yarn cross-env NODE_ENV=development yarn ts-node src/server/app.ts --ci",
     "lint:typecheck": "npx -y tsc",
     "lint:eslint": "yarn eslint --quiet \"**/*.{js,jsx,ts,tsx}\"",
-    "lint:styles": "stylelint src/**/*.scss",
+    "lint:styles": "stylelint \"src/**/*.scss\"",
     "lint:swagger2openapi": "node node_modules/.bin/oas-validate tmp/swagger.json",
     "lint": "run-p lint:*",
     "prelint:swagger2openapi": "yarn openapi:v3",
@@ -178,7 +178,7 @@
     "react-syntax-highlighter": "^15.5.0",
     "react-toastify": "^9.1.3",
     "react-use-ripple": "^1.5.2",
-    "reactstrap": "^9.2.0",
+    "reactstrap": "^9.2.2",
     "reconnecting-websocket": "^4.4.0",
     "redis": "^3.0.2",
     "rehype-katex": "^6.0.2",
@@ -194,7 +194,7 @@
     "remark-toc": "^8.0.1",
     "remark-wiki-link": "^1.0.4",
     "sanitize-filename": "^1.6.3",
-    "socket.io": "^4.7.2",
+    "socket.io": "^4.7.5",
     "stream-to-promise": "^3.0.0",
     "string-width": "=4.2.2",
     "superjson": "^1.9.1",
@@ -210,11 +210,12 @@
     "validator": "^13.7.0",
     "ws": "^8.3.0",
     "xss": "^1.0.14",
-    "y-mongodb-provider": "^0.1.7",
-    "y-socket.io": "^1.1.0",
-    "yjs": "^13.6.12"
+    "y-mongodb-provider": "^0.1.10",
+    "y-socket.io": "^1.1.3",
+    "yjs": "^13.6.15"
   },
   "// comments for defDependencies": {
+    "bootstrap": "v5.3.3 has a bug. refs: https://github.com/twbs/bootstrap/issues/39798",
     "@handsontable/react": "v3 requires handsontable >= 7.0.0.",
     "handsontable": "v7.0.0 or above is no loger MIT lisence."
   },
@@ -242,7 +243,7 @@
     "@vitejs/plugin-react": "^4.2.1",
     "@vitest/coverage-v8": "^0.34.6",
     "babel-loader": "^8.2.5",
-    "bootstrap": "^5.3.3",
+    "bootstrap": "=5.3.2",
     "connect-browser-sync": "^2.1.0",
     "cypress-real-events": "^1.12.0",
     "diff2html": "^3.4.47",
@@ -279,7 +280,7 @@
     "sass": "^1.53.0",
     "simple-load-script": "^1.0.2",
     "simplebar-react": "^2.3.6",
-    "socket.io-client": "^4.2.0",
+    "socket.io-client": "^4.7.5",
     "source-map-loader": "^4.0.1",
     "swagger2openapi": "^7.0.8",
     "tsc-alias": "^1.2.9"

+ 0 - 147
apps/app/src/client/models/MarkdownTable.js

@@ -1,147 +0,0 @@
-import csvToMarkdown from 'csv-to-markdown-table';
-import { markdownTable } from 'markdown-table';
-import stringWidth from 'string-width';
-
-// https://github.com/markdown-it/markdown-it/blob/d29f421927e93e88daf75f22089a3e732e195bd2/lib/rules_block/table.js#L83
-// https://regex101.com/r/7BN2fR/7
-const tableAlignmentLineRE = /^[-:|][-:|\s]*$/;
-const tableAlignmentLineNegRE = /^[^-:]*$/; // it is need to check to ignore empty row which is matched above RE
-const linePartOfTableRE = /^\|[^\r\n]*|[^\r\n]*\|$|([^|\r\n]+\|[^|\r\n]*)+/; // own idea
-
-const defaultOptions = { stringLength: stringWidth };
-
-/**
- * markdown table class for markdown-table module
- *   ref. https://github.com/wooorm/markdown-table
- */
-export default class MarkdownTable {
-
-  constructor(table, options) {
-    this.table = table || [];
-    this.options = Object.assign(options || {}, defaultOptions);
-
-    this.toString = this.toString.bind(this);
-  }
-
-  toString() {
-    return markdownTable(this.table, this.options);
-  }
-
-  /**
-   * returns cloned Markdowntable instance
-   * (This method clones only the table field.)
-   */
-  clone() {
-    const newTable = [];
-    for (let i = 0; i < this.table.length; i++) {
-      newTable.push([].concat(this.table[i]));
-    }
-    return new MarkdownTable(newTable, this.options);
-  }
-
-  /**
-   * normalize all cell data(trim & convert the newline character to space or pad '' if cell data is null)
-   */
-  normalizeCells() {
-    for (let i = 0; i < this.table.length; i++) {
-      for (let j = 0; j < this.table[i].length; j++) {
-        if (this.table[i][j] != null) {
-          this.table[i][j] = this.table[i][j].trim().replace(/\r?\n/g, ' ');
-        }
-        else {
-          this.table[i][j] = '';
-        }
-      }
-    }
-
-    return this;
-  }
-
-  /**
-   * return a MarkdownTable instance made from a string of HTML table tag
-   *
-   * If a parser error occurs, an error object with an error message is thrown.
-   * The error message is a innerHTML, so must not assign it into element.innerHTML because it can lead to Mutation-based XSS
-   */
-  static fromHTMLTableTag(str) {
-    // set up DOMParser
-    const domParser = new (window.DOMParser)();
-
-    // use DOMParser to prevent DOM based XSS (https://developer.mozilla.org/en-US/docs/Web/API/DOMParser)
-    const dom = domParser.parseFromString(str, 'application/xml');
-
-    if (dom.querySelector('parsererror')) {
-      throw new Error(dom.documentElement.innerHTML);
-    }
-
-    const tableElement = dom.querySelector('table');
-    const trElements = tableElement.querySelectorAll('tr');
-
-    const table = [];
-    let maxRowSize = 0;
-    for (let i = 0; i < trElements.length; i++) {
-      const row = [];
-      const cellElements = trElements[i].querySelectorAll('th,td');
-      for (let j = 0; j < cellElements.length; j++) {
-        row.push(cellElements[j].innerHTML);
-      }
-      table.push(row);
-
-      if (maxRowSize < row.length) maxRowSize = row.length;
-    }
-
-    const align = [];
-    for (let i = 0; i < maxRowSize; i++) {
-      align.push('');
-    }
-
-    return new MarkdownTable(table, { align });
-  }
-
-  /**
-   * return a MarkdownTable instance made from a string of delimiter-separated values
-   */
-  static fromDSV(str, delimiter) {
-    return MarkdownTable.fromMarkdownString(csvToMarkdown(str, delimiter, true));
-  }
-
-  /**
-   * return a MarkdownTable instance
-   *   ref. https://github.com/wooorm/markdown-table
-   * @param {string} str markdown string
-   */
-  static fromMarkdownString(str) {
-    const arrMDTableLines = str.split(/(\r\n|\r|\n)/);
-    const contents = [];
-    let aligns = [];
-    for (let n = 0; n < arrMDTableLines.length; n++) {
-      const line = arrMDTableLines[n];
-
-      if (tableAlignmentLineRE.test(line) && !tableAlignmentLineNegRE.test(line)) {
-        // parse line which described alignment
-        const alignRuleRE = [
-          { align: 'c', regex: /^:-+:$/ },
-          { align: 'l', regex: /^:-+$/ },
-          { align: 'r', regex: /^-+:$/ },
-        ];
-        let lineText = '';
-        lineText = line.replace(/^\||\|$/g, ''); // strip off pipe charactor which is placed head of line and last of line.
-        lineText = lineText.replace(/\s*/g, '');
-        aligns = lineText.split(/\|/).map((col) => {
-          const rule = alignRuleRE.find((rule) => { return col.match(rule.regex) });
-          return (rule != null) ? rule.align : '';
-        });
-      }
-      else if (linePartOfTableRE.test(line)) {
-        // parse line whether header or body
-        let lineText = '';
-        lineText = line.replace(/\s*\|\s*/g, '|');
-        lineText = lineText.replace(/^\||\|$/g, ''); // strip off pipe charactor which is placed head of line and last of line.
-        const row = lineText.split(/\|/);
-        contents.push(row);
-      }
-    }
-    return (new MarkdownTable(contents, { align: aligns }));
-  }
-
-}

+ 1 - 1
apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts

@@ -4,7 +4,7 @@ import type EventEmitter from 'events';
 
 import { Origin } from '@growi/core';
 
-import type MarkdownTable from '~/client/models/MarkdownTable';
+import type { MarkdownTable } from '@growi/editor';
 import { extractRemoteRevisionDataFromErrorObj, updatePage as _updatePage } from '~/client/services/update-page';
 import { getMarkdownTableFromLine, replaceMarkdownTableInMarkdown } from '~/components/Page/markdown-table-util-for-view';
 import { useShareLinkId } from '~/stores/context';

+ 3 - 1
apps/app/src/components/Admin/App/MaskedInput.module.scss

@@ -1,3 +1,5 @@
+/* stylelint-disable selector-class-pattern */
+
 .MaskedInput {
   position: relative;
   display: flex;
@@ -5,7 +7,7 @@
 
 .PasswordReveal {
   position: absolute;
-  top: 0rem;
+  top: 0;
   right: 0.5rem;
   left: auto;
   font-size: 1.4rem;

+ 1 - 0
apps/app/src/components/Admin/UserManagement.module.scss

@@ -4,6 +4,7 @@
 .search-typeahead :global {
   position: relative;
   width: 100%;
+
   // corner radius
   border-top-right-radius: bs.$border-radius;
   border-bottom-right-radius: bs.$border-radius;

+ 0 - 1
apps/app/src/components/Common/CopyDropdown/CopyDropdown.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
 
 .grw-copy-dropdown :global {

+ 0 - 2
apps/app/src/components/Common/DrawerToggler/DrawerToggler.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/variables' as var;
 
 
@@ -7,7 +6,6 @@
   .btn {
     --bs-btn-color: rgba(var(--bs-tertiary-color-rgb), 0.5);
     --bs-btn-bg: transparent;
-
     --bs-btn-hover-color: rgba(var(--bs-tertiary-color-rgb), 0.7);
 
     width: var.$grw-sidebar-nav-width;

+ 0 - 1
apps/app/src/components/Common/PagePathNav/PagePathNav.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
 
 .grw-mx-02em {

+ 2 - 1
apps/app/src/components/Common/PageViewLayout.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/mixins';
 @use '~/styles/variables' as var;
 
@@ -9,6 +8,7 @@ $page-view-layout-margin-top: 32px;
 
 .page-view-layout :global {
   $page-content-footer-min-heigh: 130px;
+
   min-height: calc(100vh - #{$subnavigation-height + $page-view-layout-margin-top + $page-content-footer-min-heigh});
 }
 
@@ -42,6 +42,7 @@ $page-view-layout-margin-top: 32px;
     position: sticky;
 
     $page-path-nav-height: 99px;
+
     top: calc($subnavigation-height + $page-view-layout-margin-top + $page-path-nav-height + 4px);
   }
 }

+ 1 - 1
apps/app/src/components/CustomNavigation/CustomNav.module.scss

@@ -10,7 +10,7 @@
   }
 
   .grw-nav-slide-hr {
-    border-top: 0rem;
+    border-top: 0;
     border-bottom: 3px solid;
     transition: 0.3s ease-in-out;
   }

+ 2 - 2
apps/app/src/components/DescendantsPageListModal.module.scss

@@ -1,7 +1,7 @@
 .grw-descendants-page-list-modal :global {
   .modal-header {
     button.btn-close {
-      margin: auto 0rem auto auto;
+      margin: auto 0 auto auto;
     }
   }
 
@@ -13,6 +13,6 @@
     max-height: calc(100vh - 100px);
   }
   ul.pagination {
-    margin-bottom: 0rem;
+    margin-bottom: 0;
   }
 }

+ 4 - 0
apps/app/src/components/ItemsTree/ItemsTree.module.scss

@@ -0,0 +1,4 @@
+/* stylelint-disable-next-line block-no-empty */
+.items-tree :global {
+
+}

+ 2 - 0
apps/app/src/components/ItemsTree/ItemsTreeContentSkeleton.module.scss

@@ -2,10 +2,12 @@
 
 .text-skeleton-level1 {
   @include mixins.grw-skeleton-text($font-size:16px, $line-height: 40px);
+
   padding-left: 12px;
 }
 
 .text-skeleton-level2 {
   @extend .text-skeleton-level1;
+
   padding-left: 12px + 10px * 2;
 }

+ 3 - 1
apps/app/src/components/Layout/Admin.module.scss

@@ -114,6 +114,7 @@ $slack-work-space-name-card-border: #efc1f6;
       border-width: 2px;
     }
   }
+
   // TODO: change to utility class on Bootstrap 5
   .slack-connection-log {
     .slack-connection-log-title {
@@ -173,6 +174,7 @@ $slack-work-space-name-card-border: #efc1f6;
       &.with-proxy {
         .hr-container {
           margin-top: 40px;
+
           @include media-breakpoint-up(lg) {
             margin-top: 65px;
           }
@@ -189,7 +191,7 @@ $slack-work-space-name-card-border: #efc1f6;
   //// TODO: migrate to Bootstrap 4
   //// omit all .btn-toggle and use Switches
   //// https://getbootstrap.com/docs/4.2/components/forms/#switches
-  //
+
   // Toggle Twitter Bootstrap button class when active
   // https://jsfiddle.net/ms040m01/3/
   // @mixin active-color($color, $bg-color, $border-color) {

+ 28 - 0
apps/app/src/components/Layout/BasicLayout.module.scss

@@ -0,0 +1,28 @@
+@use '@growi/core-styles/scss/bootstrap/init' as bs;
+@use '~/styles/mixins';
+
+
+// for react-toastify
+.grw-basic-layout :global {
+  .Toastify .Toastify__toast-container {
+    top: 2.5em;
+
+    @include bs.media-breakpoint-down(md) {
+      top: 6.5em;
+    }
+  }
+}
+
+.grw-basic-layout {
+  @include mixins.with-editing() {
+    .Toastify .Toastify__toast-container {
+      top: 5em;
+
+      @include bs.media-breakpoint-down(md) {
+        top: 7em;
+      }
+    }
+  }
+}
+
+

+ 7 - 1
apps/app/src/components/Layout/BasicLayout.tsx

@@ -9,6 +9,12 @@ import { Sidebar } from '../Sidebar';
 
 import { RawLayout } from './RawLayout';
 
+
+import styles from './BasicLayout.module.scss';
+
+const moduleClass = styles['grw-basic-layout'] ?? '';
+
+
 const AlertSiteUrlUndefined = dynamic(() => import('../AlertSiteUrlUndefined').then(mod => mod.AlertSiteUrlUndefined), { ssr: false });
 const DeleteAttachmentModal = dynamic(() => import('../PageAttachment/DeleteAttachmentModal').then(mod => mod.DeleteAttachmentModal), { ssr: false });
 const HotkeysManager = dynamic(() => import('../Hotkeys/HotkeysManager'), { ssr: false });
@@ -35,7 +41,7 @@ type Props = {
 
 export const BasicLayout = ({ children, className }: Props): JSX.Element => {
   return (
-    <RawLayout className={`${className ?? ''}`}>
+    <RawLayout className={`${moduleClass} ${className ?? ''}`}>
       <DndProvider backend={HTML5Backend}>
 
         <div className="page-wrapper flex-row">

+ 15 - 11
apps/app/src/components/Layout/NoLoginLayout.module.scss

@@ -1,3 +1,5 @@
+/* stylelint-disable scss/no-global-function-names */
+
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
 @use '@growi/core-styles/scss/variables/growi-official-colors' as var;
 
@@ -5,6 +7,11 @@
 .nologin :global {
   height: 100vh;
 
+  .nologin-header,
+  .nologin-dialog {
+    max-width: 480px;
+  }
+
   // layout
   .main {
     width: 100vw;
@@ -54,11 +61,6 @@
     }
   }
 
-  .nologin-header,
-  .nologin-dialog {
-    max-width: 480px;
-  }
-
 }
 
 .link-switch {
@@ -80,9 +82,10 @@
   .nologin :global {
     // background color
     $color-gradient: #3c465c;
-    background: linear-gradient(45deg, darken($color-gradient, 30%) 0%, hsla(340, 100%, 55%, 0) 70%),
-      linear-gradient(135deg, var.$growi-green 10%, hsla(225, 95%, 50%, 0) 70%), linear-gradient(225deg, var.$growi-blue 10%, hsla(140, 90%, 50%, 0) 80%),
-      linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35, 95%, 55%, 0) 70%);
+
+    background: linear-gradient(45deg, darken($color-gradient, 30%) 0%, hsla(340deg, 100%, 55%, 0%) 70%),
+      linear-gradient(135deg, var.$growi-green 10%, hsla(225deg, 95%, 50%, 0%) 70%), linear-gradient(225deg, var.$growi-blue 10%, hsla(140deg, 90%, 50%, 0%) 80%),
+      linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35deg, 95%, 55%, 0%) 70%);
 
     .nologin-header {
       background-color: rgba(white, 0.3);
@@ -134,9 +137,10 @@
   .nologin :global {
     // background color
     $color-gradient: #3c465c;
-    background: linear-gradient(45deg, darken($color-gradient, 30%) 0%, hsla(340, 100%, 55%, 0) 70%),
-      linear-gradient(135deg, var.$growi-green 10%, hsla(225, 95%, 50%, 0) 70%), linear-gradient(225deg, var.$growi-blue 10%, hsla(140, 90%, 50%, 0) 80%),
-      linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35, 95%, 55%, 0) 70%);
+
+    background: linear-gradient(45deg, darken($color-gradient, 30%) 0%, hsla(340deg, 100%, 55%, 0%) 70%),
+      linear-gradient(135deg, var.$growi-green 10%, hsla(225deg, 95%, 50%, 0%) 70%), linear-gradient(225deg, var.$growi-blue 10%, hsla(140deg, 90%, 50%, 0%) 80%),
+      linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35deg, 95%, 55%, 0%) 70%);
 
     .nologin-header {
       background-color: rgba(black, 0.3);

+ 2 - 3
apps/app/src/components/LoginForm/LoginForm.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/atoms/placeholders/buttons';
 
 .login-form :global {
@@ -24,8 +23,8 @@
   }
 
   .text-line {
-    &:before,
-    &:after {
+    &::before,
+    &::after {
       flex-grow: 1;
       height: 1px;
       margin:0 1em;

+ 0 - 0
apps/app/src/components/Me/ColorModeSettings.module.scss


+ 0 - 2
apps/app/src/components/Me/ColorModeSettings.tsx

@@ -4,8 +4,6 @@ import { useTranslation } from 'react-i18next';
 
 import { Themes, useNextThemes } from '~/stores/use-next-themes';
 
-// import styles from './ColorModeSettings.module.scss';
-
 
 type ColorModeSettingsButtonProps = {
   isActive: boolean,

+ 1 - 1
apps/app/src/components/Navbar/GrowiContextualSubNavigation.module.scss

@@ -9,7 +9,7 @@
   }
 }
 
-@include mixins.editing() {
+@include mixins.at-editing() {
   .grw-contextual-sub-navigation {
     position: fixed;
     right: 0;

+ 1 - 0
apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss

@@ -4,6 +4,7 @@
 .grw-navbar-bottom :global {
   // apply transition
   transition-property: bottom;
+
   @include mixins.apply-navigation-transition();
 
   .navbar {

+ 2 - 0
apps/app/src/components/Navbar/PageEditorModeManager.module.scss

@@ -20,6 +20,7 @@
 .grw-page-editor-mode-manager-skeleton :global {
   width: 90px;
   height: 38px;
+
   @include bs.media-breakpoint-up(md) {
     width: 179px;
     height: 30px;
@@ -47,6 +48,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-page-editor-mode-manager :global {
     .btn {

+ 1 - 1
apps/app/src/components/Page/markdown-table-util-for-view.ts

@@ -1,4 +1,4 @@
-import MarkdownTable from '~/client/models/MarkdownTable';
+import { MarkdownTable } from '@growi/editor';
 
 export const getMarkdownTableFromLine = (markdown: string, bol: number, eol: number): MarkdownTable => {
   const tableLines = markdown.split(/\r\n|\r|\n/).slice(bol - 1, eol).join('\n');

+ 2 - 2
apps/app/src/components/PageAccessoriesModal/PageAccessoriesModal.module.scss

@@ -1,7 +1,7 @@
 .grw-page-accessories-modal :global {
   .modal-header {
     button.btn-close {
-      margin: auto 0rem auto auto;
+      margin: auto 0 auto auto;
     }
   }
 
@@ -13,6 +13,6 @@
     max-height: calc(100vh - 100px);
   }
   ul.pagination {
-    margin-bottom: 0rem;
+    margin-bottom: 0;
   }
 }

+ 5 - 6
apps/app/src/components/PageComment/Comment.module.scss

@@ -1,14 +1,12 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '../../styles/variables' as var;
-@use './_comment-inheritance';
+@use './comment-inheritance';
 
 .comment-styles :global {
 
   .page-comment {
     position: relative;
     pointer-events: none;
-
     scroll-margin-top: var.$grw-scroll-margin-top-in-view;
 
     // background
@@ -49,8 +47,9 @@
     }
 
     // older comments
-    &.page-comment-older {
-    }
+    // &.page-comment-older {
+    // }
+
     // newer comments
     &.page-comment-newer {
       opacity: 0.7;
@@ -71,7 +70,6 @@
     .page-comment-meta {
       display: flex;
       justify-content: flex-end;
-
       font-size: 0.9em;
       color: bs.$gray-400;
     }
@@ -84,6 +82,7 @@
     height: 66px;
     padding: 1em;
     margin-left: 4.5em;
+
     @include bs.media-breakpoint-down(xs) {
       margin-left: 3.5em;
     }

+ 1 - 2
apps/app/src/components/PageComment/CommentEditor.module.scss

@@ -31,8 +31,7 @@
     min-height: comment-inheritance.$codemirror-default-height !important;
   }
   .comment-preview-container {
-    min-height: page-editor-inheritance.$navbar-editor-height
-      + comment-inheritance.$codemirror-default-height;
+    min-height: page-editor-inheritance.$navbar-editor-height + comment-inheritance.$codemirror-default-height;
     padding-top: 0.5em;
   }
 }

+ 1 - 0
apps/app/src/components/PageComment/CommentPreview.module.scss

@@ -1,2 +1,3 @@
+/* stylelint-disable-next-line block-no-empty */
 .grw-comment-preview {
 }

+ 1 - 0
apps/app/src/components/PageComment/DeleteCommentModal.module.scss

@@ -3,6 +3,7 @@
   .modal-content .modal-body {
     .comment-body {
       max-height: 13em;
+
       // scrollable
       overflow-y: auto;
     }

+ 1 - 0
apps/app/src/components/PageComment/SwitchingButtonGroup.module.scss

@@ -31,6 +31,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .btn-group-switching :global {
     .btn {

+ 3 - 3
apps/app/src/components/PageComment/_comment-inheritance.scss

@@ -5,7 +5,7 @@
   padding: 1em;
 
   // speech balloon
-  &:before {
+  &::before {
     position: absolute;
     top: 1.5em;
     left: -1em;
@@ -32,8 +32,8 @@ $codemirror-default-height: 300px;
 @include bs.color-mode(light) {
   %bg-comment {
     background-color: rgba( bs.$gray-200, 0.5 );
-    border: 1px solid bs.$gray-200;
     backdrop-filter: blur(10px);
+    border: 1px solid bs.$gray-200;
   }
 }
 
@@ -41,7 +41,7 @@ $codemirror-default-height: 300px;
 @include bs.color-mode(dark) {
   %bg-comment {
     background-color: rgba( bs.$gray-800, 0.3 );
-    border: 1px solid bs.$gray-700;
     backdrop-filter: blur(10px);
+    border: 1px solid bs.$gray-700;
   }
 }

+ 1 - 0
apps/app/src/components/PageContentFooter.module.scss

@@ -6,6 +6,7 @@
     font-size: 0.95em;
   }
 }
+
 // TODO: Should Soft Coding see: https://github.com/weseek/growi/pull/6404
 .page-content-footer-skeleton :global {
   width: 300px;

+ 2 - 2
apps/app/src/components/PageControls/BookmarkButtons.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 .btn-group-bookmark :global {
@@ -13,12 +11,14 @@
   }
   .total-counts {
     @extend %btn-total-counts-basis;
+
     padding-left: 5px;
   }
 }
 
 // == Colors
 .btn-group-bookmark :global {
+  /* stylelint-disable-next-line no-descending-specificity */
   .btn-bookmark {
     @include btn-muted.colorize(bs.$orange);
   }

+ 1 - 2
apps/app/src/components/PageControls/LikeButtons.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 .btn-group-like :global {
@@ -13,6 +11,7 @@
   }
   .total-counts {
     @extend %btn-total-counts-basis;
+
     padding-left: 5px;
   }
 }

+ 0 - 2
apps/app/src/components/PageControls/PageControls.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 // PageItemControl styles

+ 15 - 10
apps/app/src/components/PageControls/PageControls.tsx

@@ -66,7 +66,7 @@ const Tags = (props: TagsProps): JSX.Element => {
 };
 
 type WideViewMenuItemProps = AdditionalMenuItemsRendererProps & {
-  onClickMenuItem: (newValue: boolean) => void,
+  onClickMenuItem: () => void,
   expandContentWidth?: boolean,
 }
 
@@ -77,24 +77,27 @@ const WideViewMenuItem = (props: WideViewMenuItemProps): JSX.Element => {
     onClickMenuItem, expandContentWidth,
   } = props;
 
+  const menuItemClickedHandler = useCallback((e: React.MouseEvent<HTMLInputElement>) => {
+    e.preventDefault();
+    onClickMenuItem();
+  }, [onClickMenuItem]);
+
   return (
-    <DropdownItem
-      onClick={() => onClickMenuItem(!(expandContentWidth))}
-      className="grw-page-control-dropdown-item"
+    <div
+      className="grw-page-control-dropdown-item dropdown-item"
+      onClick={menuItemClickedHandler}
     >
       <div className="form-check form-switch ms-1">
         <input
-          id="switchContentWidth"
           className="form-check-input"
           type="checkbox"
           checked={expandContentWidth}
-          onChange={() => {}}
         />
-        <label className="form-label form-check-label" htmlFor="switchContentWidth">
+        <label className="form-label form-check-label">
           { t('wide_view') }
         </label>
       </div>
-    </DropdownItem>
+    </div>
   );
 };
 
@@ -224,7 +227,9 @@ const PageControlsSubstance = (props: PageControlsSubstanceProps): JSX.Element =
     onClickDeleteMenuItem(pageToDelete);
   }, [onClickDeleteMenuItem, pageId, pageInfo, path, revisionId]);
 
-  const switchContentWidthClickHandler = useCallback(async(newValue: boolean) => {
+  const switchContentWidthClickHandler = useCallback(() => {
+
+    const newValue = !expandContentWidth;
     if (onClickSwitchContentWidth == null || (isGuestUser ?? true) || (isReadOnlyUser ?? true)) {
       logger.warn('Could not switch content width', {
         onClickSwitchContentWidth: onClickSwitchContentWidth == null ? 'null' : 'not null',
@@ -242,7 +247,7 @@ const PageControlsSubstance = (props: PageControlsSubstanceProps): JSX.Element =
     catch (err) {
       toastError(err);
     }
-  }, [isGuestUser, isReadOnlyUser, onClickSwitchContentWidth, pageId, pageInfo]);
+  }, [expandContentWidth, isGuestUser, isReadOnlyUser, onClickSwitchContentWidth, pageId, pageInfo]);
 
   const additionalMenuItemOnTopRenderer = useMemo(() => {
     if (!isIPageInfoForEntity(pageInfo)) {

+ 0 - 2
apps/app/src/components/PageControls/SearchButton.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 .btn-search :global {

+ 0 - 2
apps/app/src/components/PageControls/SeenUserInfo.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 .grw-seen-user-info :global {

+ 0 - 2
apps/app/src/components/PageControls/SubscribeButton.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
-
 @use './button-styles';
 
 .btn-subscribe :global {

+ 0 - 3
apps/app/src/components/PageCreateModal.module.scss

@@ -2,9 +2,6 @@
   .page-today-input1 {
     width: 60px;
   }
-  .page-today-input2 {
-  }
-
   .grw-btn-create-page {
     min-width: 90px;
   }

+ 1 - 0
apps/app/src/components/PageEditor/EditorNavbar/EditorNavbar.module.scss

@@ -2,6 +2,7 @@
 
 .editor-navbar :global {
   min-height: 72px;
+
   @include bs.media-breakpoint-down(sm) {
     min-height: 96px;
   }

+ 1 - 1
apps/app/src/components/PageEditor/EditorNavbarBottom.module.scss

@@ -2,7 +2,7 @@
 @use '~/styles/variables' as var;
 @use '~/styles/mixins';
 
-@include mixins.editing() {
+@include mixins.at-editing() {
   .grw-editor-navbar-bottom :global {
     .grw-grant-selector {
       max-width: 250px;

+ 5 - 4
apps/app/src/components/PageEditor/GridEditModal.module.scss

@@ -6,13 +6,13 @@
   .mobile-preview {
     .row {
       height: 140px;
-      margin: 0px;
+      margin: 0;
     }
   }
   .desktop-preview {
     .row {
       div {
-        padding: 0px;
+        padding: 0;
       }
     }
   }
@@ -20,7 +20,7 @@
   .tablet-preview {
     .row {
       div {
-        padding: 0px;
+        padding: 0;
       }
     }
   }
@@ -29,13 +29,14 @@
     width: 75%;
     .row {
       div {
-        padding: 0px;
+        padding: 0;
       }
     }
   }
 
   .grid-division-menu {
     width: 60vw;
+
     @include bs.media-breakpoint-down(lg) {
       width: 80vw;
     }

+ 1 - 1
apps/app/src/components/PageEditor/HandsontableModal.module.scss

@@ -35,7 +35,7 @@
       padding-right: 35px;
       padding-left: 10px;
 
-      i:before {
+      i::before {
         position: absolute;
         top: 6px;
         right: 8px;

+ 1 - 1
apps/app/src/components/PageEditor/HandsontableModal.tsx

@@ -1,5 +1,6 @@
 import React, { useState } from 'react';
 
+import { MarkdownTable } from '@growi/editor';
 import { useHandsontableModalForEditor } from '@growi/editor/src/stores/use-handsontable';
 import { HotTable } from '@handsontable/react';
 import type Handsontable from 'handsontable';
@@ -10,7 +11,6 @@ import {
 } from 'reactstrap';
 import { debounce } from 'throttle-debounce';
 
-import MarkdownTable from '~/client/models/MarkdownTable';
 import { replaceFocusedMarkdownTableWithEditor, getMarkdownTable } from '~/components/PageEditor/markdown-table-util-for-editor';
 import { useHandsontableModal } from '~/stores/modal';
 

+ 1 - 1
apps/app/src/components/PageEditor/LinkEditModal.tsx

@@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback } from 'react';
 
 import path from 'path';
 
-import Linker from '@growi/editor/src/services/link-util/Linker';
+import { Linker } from '@growi/editor/src/services-internal';
 import { useLinkEditModal } from '@growi/editor/src/stores/use-link-edit-modal';
 import { useTranslation } from 'next-i18next';
 import {

+ 2 - 2
apps/app/src/components/PageEditor/LinkEditPreview.module.scss

@@ -1,8 +1,8 @@
 .linkedit-preview {
   .page-editor-preview-body {
     max-height: 70vh;
-    padding-top: 0px;
-    margin: 0px -10px 0px -10px;
+    padding-top: 0;
+    margin: 0 -10px;
     .wiki {
       overflow-y: scroll;
       font-size: 0.5rem;

+ 1 - 1
apps/app/src/components/PageEditor/MarkdownTableDataImportForm.tsx

@@ -1,12 +1,12 @@
 import React, { useState } from 'react';
 
+import { MarkdownTable } from '@growi/editor';
 import { useTranslation } from 'next-i18next';
 import {
   Button,
   Collapse,
 } from 'reactstrap';
 
-import MarkdownTable from '~/client/models/MarkdownTable';
 
 type MarkdownTableDataImportFormProps = {
   onCancel: () => void,

+ 4 - 3
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -149,7 +149,10 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
     // set to ref
     initialValueRef.current = initialValue;
   }, [initialValue]);
-  const [markdownToPreview, setMarkdownToPreview] = useState<string>(initialValue);
+
+  const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);
+
+  const [markdownToPreview, setMarkdownToPreview] = useState<string>(codeMirrorEditor?.getDoc() ?? '');
   const setMarkdownPreviewWithDebounce = useMemo(() => debounce(100, throttle(150, (value: string) => {
     setMarkdownToPreview(value);
   })), []);
@@ -159,8 +162,6 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   }, [setMarkdownPreviewWithDebounce]);
 
 
-  const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);
-
   const { scrollEditorHandler, scrollPreviewHandler } = useScrollSync(GlobalCodeMirrorEditorKey.MAIN, previewRef);
 
   const scrollEditorHandlerThrottle = useMemo(() => throttle(25, scrollEditorHandler), [scrollEditorHandler]);

+ 1 - 1
apps/app/src/components/PageEditor/Preview.module.scss

@@ -3,7 +3,7 @@
 .page-editor-preview-body :global {
   .wiki {
     max-width: 980px;
-    padding: 0px 15px;
+    padding: 0 15px;
     margin: 0 auto;
   }
 }

+ 1 - 2
apps/app/src/components/PageEditor/markdown-table-util-for-editor.ts

@@ -1,6 +1,5 @@
 import type { EditorView } from '@codemirror/view';
-
-import MarkdownTable from '~/client/models/MarkdownTable';
+import { MarkdownTable } from '@growi/editor';
 
 // https://regex101.com/r/7BN2fR/10
 const linePartOfTableRE = /^([^\r\n|]*)\|(([^\r\n|]*\|)+)$/;

+ 1 - 0
apps/app/src/components/PageHeader/PageHeader.module.scss

@@ -1,2 +1,3 @@
+/* stylelint-disable-next-line block-no-empty */
 .page-header :global {
 }

+ 2 - 2
apps/app/src/components/PagePresentationModal.module.scss

@@ -1,7 +1,7 @@
-@use '~/styles/_modal';
+@use '~/styles/modal';
 
 .grw-presentation-modal :global {
-
+  /* stylelint-disable-next-line length-zero-no-unit */
   @include modal.expand-modal-fullscreen(false, false, 0px);
 
   .modal-content {

+ 1 - 1
apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss

@@ -14,7 +14,7 @@
 
 @include bs.media-breakpoint-down(sm) {
   .btn-page-accessories :global {
-    box-shadow: 0px 3px 6px rgba(black, 0.15);
+    box-shadow: 0 3px 6px rgba(black, 0.15);
   }
 }
 

+ 1 - 0
apps/app/src/components/PageSideContents/PageSideContents.module.scss

@@ -1,2 +1,3 @@
+/* stylelint-disable-next-line block-no-empty */
 .grw-page-accessories-controls :global {
 }

+ 1 - 1
apps/app/src/components/PageStatusAlert.module.scss

@@ -4,7 +4,7 @@
 .grw-page-status-alert :global {
   $margin-bottom: var.$grw-navbar-bottom-height + 10px;
 
-  box-shadow: 0px 2px 4px #0000004d;
+  box-shadow: 0 2px 4px #0000004d;
   opacity: 0.9;
 
   @include bs.media-breakpoint-down(sm) {

+ 2 - 1
apps/app/src/components/PageTags/TagLabels.module.scss

@@ -35,7 +35,8 @@ $grw-tag-label-font-size: 12px;
 
 .grw-tag-icon-button {
   padding: 6px 8px;
+
   @include bs.media-breakpoint-down(sm) {
-    box-shadow: 0px 3px 6px rgba(black, 0.15);
+    box-shadow: 0 3px 6px rgba(black, 0.15);
   }
 }

+ 0 - 1
apps/app/src/components/RevisionComparer/RevisionComparer.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
 
 .revision-compare :global {

+ 0 - 1
apps/app/src/components/SearchPage/SearchControl.module.scss

@@ -1,6 +1,5 @@
 
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/ui/scss/atoms/btn-muted';
 
 // == Colors

+ 1 - 0
apps/app/src/components/SearchPage/SearchResultContent.module.scss

@@ -1,5 +1,6 @@
 @use '~/styles/mixins';
 
+/* stylelint-disable-next-line block-no-empty */
 .search-result-content :global {
 }
 

+ 1 - 0
apps/app/src/components/SearchTypeahead.module.scss

@@ -3,6 +3,7 @@
 .search-typeahead :global {
   position: relative;
   width: 100%;
+
   // corner radius
   border-top-right-radius: bs.$border-radius;
   border-bottom-right-radius: bs.$border-radius;

+ 9 - 5
apps/app/src/components/ShortcutsModal.module.scss

@@ -25,20 +25,22 @@
 
   // see http://coliss.com/articles/build-websites/operation/css/css-apple-keyboard-style-by-nrjmadan.html
   .key {
-    /*Box Properties*/
+    /* Box Properties */
     display: inline-block;
     width: 36px;
     height: 36px;
-    margin: 0px 4px;
-    /*Text Properties*/
+    margin: 0 4px;
+
+    /* Text Properties */
     font: 18px/36px Helvetica, serif;
     color: bs.$secondary;
     text-align: center;
     text-transform: uppercase;
     background: white;
     border-radius: 4px;
-    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.5);
-    /* SVG Properties*/
+    box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 50%);
+
+    /* SVG Properties */
     polygon {
       fill: bs.$secondary;
     }
@@ -63,9 +65,11 @@
       display: flex;
       align-items: center;
       justify-content: flex-end;
+
       // width: 180px;
       height: 41px;
     }
+
     // dd {
     //   margin-left: 190px;
     // }

+ 1 - 3
apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss

@@ -1,9 +1,6 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '@growi/core-styles/scss/variables/growi-official-colors';
-
 @use '~/styles/variables' as var;
-
 @use '../button-styles';
 
 // GROWI Logo
@@ -55,6 +52,7 @@
     $grw-page-editor-mode-manager-width: 140px;
     $gap: 24px;
     $grw-contextual-subnavigation-padding-right: 24px;
+
     width: calc(100vw - #{var.$grw-sidebar-nav-width + $grw-page-controls-width + $grw-page-editor-mode-manager-width + $grw-contextual-subnavigation-padding-right + $gap * 2});
   }
 }

+ 0 - 1
apps/app/src/components/Sidebar/PageCreateButton/CreateButton.module.scss

@@ -1,5 +1,4 @@
 @use '~/styles/variables' as var;
-
 @use '../button-styles';
 
 .btn-create :global {

+ 2 - 6
apps/app/src/components/Sidebar/PageCreateButton/DropendToggle.module.scss

@@ -1,5 +1,4 @@
 @use '~/styles/variables' as var;
-
 @use '../button-styles';
 
 .btn-toggle :global {
@@ -10,7 +9,7 @@
 
   .icon {
     top: 50%;
-    right: 0px;
+    right: 0;
     font-size: 22px;
     transform: translateY(-50%);
   }
@@ -29,10 +28,7 @@
 // hitarea
 .btn-toggle :global {
   .hitarea {
-    top: 0;
-    right: -10px;
-    bottom: 0;
-    left: 0;
+    inset: 0 -10px 0 0;
   }
 }
 

+ 0 - 2
apps/app/src/components/Sidebar/PageCreateButton/PageCreateButton.module.scss

@@ -1,2 +0,0 @@
-.grw-page-create-button :global {
-}

+ 3 - 0
apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.module.scss

@@ -10,16 +10,19 @@
 
   .grw-recent-changes-skeleton-small {
     @include grw-skeleton-text($font-size: 14px, $line-height: 16px);
+
     max-width: 120px;
   }
 
   .grw-recent-changes-skeleton-h5 {
     @include grw-skeleton-h5;
+
     max-width: 120px;
   }
 
   .grw-recent-changes-skeleton-date {
     @include grw-skeleton-text($font-size: 10px, $line-height: 12px);
+
     width: 80px;
   }
 

+ 2 - 2
apps/app/src/components/Sidebar/ResizableArea/ResizableArea.module.scss

@@ -9,8 +9,8 @@
 
 .grw-navigation-draggable :global {
   position: absolute;
-  top: 0px;
-  bottom: 0px;
+  top: 0;
+  bottom: 0;
   left: 100%;
 
   .grw-navigation-draggable-hitarea {

+ 3 - 1
apps/app/src/components/Sidebar/Sidebar.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/variables' as var;
 @use '~/styles/mixins';
 
@@ -60,6 +59,7 @@
 
       // apply transition
       transition-property: transform;
+
       @include mixins.apply-navigation-transition();
 
       &:not(.open) {
@@ -82,6 +82,7 @@
       background-color: color-mix(in srgb, var(--grw-highlight-100), var(--bs-body-bg));
     }
   }
+
   // frosted glass effect in collapsed mode
   .grw-sidebar {
     &:global {
@@ -104,6 +105,7 @@
       background-color: color-mix(in srgb, var(--grw-highlight-800), var(--bs-body-bg));
     }
   }
+
   // frosted glass effect in collapsed mode
   .grw-sidebar {
     &:global {

+ 0 - 1
apps/app/src/components/Sidebar/SidebarContents.module.scss

@@ -1,7 +1,6 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
 
 .grw-sidebar-contents :global {
-
   --bs-heading-color: var(--bs-tertiary-color);
   --bs-body-color: var(--bs-secondary-color);
   --bs-link-color-rgb: var(--bs-secondary-color-rgb);

+ 1 - 0
apps/app/src/components/Sidebar/SidebarHead/SidebarHead.module.scss

@@ -13,6 +13,7 @@
     );
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-sidebar-head :global {
     background-color: var(

+ 4 - 3
apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.module.scss

@@ -1,14 +1,13 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/variables' as var;
 @use '~/styles/mixins';
-
 @use '../button-styles';
 
 .btn-toggle-collapse :global {
   @extend %btn-basis;
 
   $height: var.$grw-sidebar-nav-width; // declare $height with the same value as the sidebar nav width
+
   height: $height;
 }
 
@@ -25,7 +24,7 @@
 }
 
 // Hide when editing
-@include mixins.editing() {
+@include mixins.at-editing() {
   .btn-toggle-collapse {
     visibility: hidden;
   }
@@ -48,6 +47,7 @@
     }
   }
 }
+
 @include bs.color-mode(light) {
   .btn-toggle-collapse {
     &:global {
@@ -58,6 +58,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .btn-toggle-collapse {
     &:global {

+ 2 - 0
apps/app/src/components/Sidebar/SidebarNav/PersonalDropdown.module.scss

@@ -25,6 +25,7 @@
 
   .personal-dropdown-item :global {
     --bs-link-color-rgb:var(--bs-gray-600);
+
     color: var(--bs-gray-600);
   }
 }
@@ -36,6 +37,7 @@
 
   .personal-dropdown-item :global {
     --bs-link-color-rgb:var(--bs-gray-500);
+
     color: var(--bs-gray-500);
   }
 }

+ 3 - 3
apps/app/src/components/Sidebar/SidebarNav/PrimaryItems.module.scss

@@ -1,7 +1,5 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '../button-styles';
-
 @use '../variables' as sidebarVar;
 
 .grw-primary-items :global {
@@ -29,7 +27,7 @@
       position: relative;
 
       // indicator
-      &:after {
+      &::after {
         position: absolute;
         top: 0;
         left: 0;
@@ -55,6 +53,7 @@
     @extend %btn-primary-color-vars;
   }
 }
+
 @include bs.color-mode(light) {
   .grw-primary-items :global {
     .btn-primary {
@@ -63,6 +62,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-primary-items :global {
     .btn-primary {

+ 2 - 1
apps/app/src/components/Sidebar/SidebarNav/SecondaryItems.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '../button-styles';
 
 
@@ -22,6 +21,7 @@
     @extend %btn-primary-color-vars;
   }
 }
+
 @include bs.color-mode(light) {
   .grw-secondary-items :global {
     .btn-primary {
@@ -30,6 +30,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-secondary-items :global {
     .btn-primary {

+ 1 - 4
apps/app/src/components/Sidebar/SidebarNav/SidebarNav.module.scss

@@ -1,10 +1,8 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/variables' as var;
 
 .grw-sidebar-nav :global {
   width: var.$grw-sidebar-nav-width;
-
   border-right : 1px solid var(--bs-border-color);
 
   .grw-sidebar-nav-secondary-container {
@@ -15,13 +13,12 @@
 
 
 // == Colors
-.grw-sidebar-nav :global {
-}
 @include bs.color-mode(light) {
   .grw-sidebar-nav :global {
     background-color: var(--grw-sidebar-nav-bg, var(--grw-highlight-100));
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-sidebar-nav :global {
     background-color: var(--grw-sidebar-nav-bg, var(--grw-highlight-800));

+ 0 - 1
apps/app/src/components/Sidebar/SidebarNav/SkeletonItem.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '../variables' as sidebarVar;
 
 .grw-skeleton-item :global {

+ 2 - 0
apps/app/src/components/Sidebar/Skeleton/DefaultContentSkelton.module.scss

@@ -3,12 +3,14 @@
 .grw-default-content-skelton :global {
   .grw-skeleton-text {
     @include mixins.grw-skeleton-text($font-size:15px, $line-height:21.42px);
+
     max-width: 160px;
     margin: 15px 0;
   }
 
   .grw-skeleton-text-full {
     @extend .grw-skeleton-text;
+
     max-width: 100%;
   }
 }

+ 0 - 2
apps/app/src/components/Sidebar/_button-styles.scss

@@ -1,5 +1,4 @@
 @use '~/styles/variables' as var;
-
 @use './variables' as sidebarVar;
 
 
@@ -9,7 +8,6 @@
 
   width: var.$grw-sidebar-nav-width;
   height: sidebarVar.$grw-sidebar-button-height;
-
   line-height: 1em;
   border: 0;
   border-radius: 0;

+ 1 - 0
apps/app/src/components/Skeleton.module.scss

@@ -1,4 +1,5 @@
 .grw-skeleton {
   --bs-list-group-color: rgba(var(--bs-tertiary-color-rgb), 0.2);
+
   background-color: var(--bs-list-group-color);
 }

+ 1 - 4
apps/app/src/components/StaffCredit/StaffCredit.module.scss

@@ -3,19 +3,16 @@
   // attached !important for updating from .modal-dialog class style
   width: 80vw !important;
   max-width: unset !important;
-
   height: 80vh !important;
   max-height: unset !important;
-
   margin: 10vh 10vw !important;
 
   // see https://css-tricks.com/old-timey-terminal-styling/
   .credit-curtain {
     padding-top: 80vh;
-
     text-shadow: 0 0 10px #c8c8c8;
     background-color: black;
-    background-image: radial-gradient(rgba(50, 100, 100, 0.75), black 120%);
+    background-image: radial-gradient(rgba(50, 100, 100, 75%), black 120%);
   }
 
   .background {

+ 0 - 1
apps/app/src/components/TableOfContents.module.scss

@@ -5,7 +5,6 @@
   z-index: 1;
   padding: 5px;
   font-size: 0.9em;
-
   border-bottom: 1px solid transparent;
 
   .revision-toc-content {

+ 1 - 0
apps/app/src/components/TagList.module.scss

@@ -17,6 +17,7 @@
     }
   }
 }
+
 @include bs.color-mode(dark) {
   .grw-tag-list :global {
     .grw-tag-count {

+ 3 - 25
apps/app/src/components/UsersHomepageFooter.module.scss

@@ -1,4 +1,5 @@
 @use '@growi/ui/scss/molecules/page_list';
+
 $grw-sidebar-content-header-height: 58px;
 $grw-sidebar-content-footer-height: 50px;
 
@@ -18,18 +19,9 @@ $grw-sidebar-content-footer-height: 50px;
             display: block;
           }
         }
-        .grw-triangle-container {
-          svg {
-            width: 12px;
-            height: 12px;
-          }
-        }
-        svg {
-          width: 20px;
-          height: 20px;
-        }
+
         min-height: 40px;
-        border-radius: 0px;
+        border-radius: 0;
 
         &.grw-bookmark-item-list {
           .picture {
@@ -62,25 +54,11 @@ $grw-sidebar-content-footer-height: 50px;
       width: fit-content !important;
       margin-right: 20px;
     }
-    svg {
-      width: 35px;
-      height: 35px;
-      margin-bottom: 6px;
-    }
     .new-bookmark-folder {
       max-height: 30px;
-      svg {
-        width: 18px;
-        height: 18px;
-      }
     }
     .grw-expand-compress-btn {
       max-height: 40px;
-      svg {
-        width: 18px;
-        height: 18px;
-        margin-bottom: 3px;
-      }
     }
     .grw-folder-tree-container {
       .grw-drop-item-area {

+ 0 - 1
apps/app/src/components/UsersHomepageFooter.tsx

@@ -2,7 +2,6 @@ import React, { useState } from 'react';
 
 import { useTranslation } from 'next-i18next';
 
-import { RecentlyCreatedIcon } from '~/components/Icons/RecentlyCreatedIcon';
 import { RecentCreated } from '~/components/RecentCreated/RecentCreated';
 import styles from '~/components/UsersHomepageFooter.module.scss';
 import { useCurrentUser } from '~/stores/context';

+ 5 - 3
apps/app/src/features/growi-plugin/client/components/Admin/PluginsExtensionPageContents/PluginCard.module.scss

@@ -1,3 +1,5 @@
+/* stylelint-disable selector-class-pattern */
+
 // TODO: Rewrite according to guidelines
 .plugin_card :global {
 
@@ -14,7 +16,7 @@
     cursor: pointer;
     border-radius: 30px;
   }
-  .switch__content:before {
+  .switch__content::before {
     position: absolute;
     top: 0;
     left: 0;
@@ -26,7 +28,7 @@
     border: 1.5px solid #E5E5EA;
     border-radius: 30px;
   }
-  .switch__content:after {
+  .switch__content::after {
     position: absolute;
     top: 50%;
     left: 50%;
@@ -58,7 +60,7 @@
     left: 21px;
   }
 
-  .switch__input:checked ~ .switch__content:after {
+  .switch__input:checked ~ .switch__content::after {
     top: 0;
     left: 0;
     width: 100%;

+ 0 - 1
apps/app/src/features/search/client/components/SearchMenuItem.module.scss

@@ -1,5 +1,4 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
-
 @use '~/styles/variables' as var;
 
 .search-menu-item :global {

+ 6 - 0
apps/app/src/linter-checker/.stylelintrc.json

@@ -0,0 +1,6 @@
+{
+  "extends": "../../../../.stylelintrc.json",
+  "ignoreFiles": [
+    "./test.scss"
+  ]
+}

+ 1 - 1
apps/app/src/linter-checker/test.scss

@@ -1,7 +1,7 @@
 /*
  * VSCode の Stylelint 設定チェック方法
  *
- * 1. .stylelintrc.json ファイル中の `src/linter-checker/test.scss` 行を削除し、
+ * 1. このディレクトリにある .stylelintrc.json ファイル中の `./test.scss` 行を削除し、
  *    このファイルを VSCode 上で開き直す
  *
  * 2. VSCode で以下のエラーが表示されていることを確認

+ 1 - 0
apps/app/src/pages/login/index.module.scss

@@ -6,6 +6,7 @@
   .nologin-header,
   .nologin-dialog {
     width: 420px;
+
     @include bs.media-breakpoint-down(sm) {
       width: 320px;
     }

+ 3 - 4
apps/app/src/server/service/yjs-connection-manager.ts

@@ -59,10 +59,9 @@ class YjsConnectionManager {
 
     await this.mdb.flushDocument(pageId);
 
-    const persistedCodeMirrorText = persistedYdoc.getText('codemirror').toString();
-    const currentCodeMirrorText = currentYdoc.getText('codemirror').toString();
-
-    if (persistedCodeMirrorText === '' && currentCodeMirrorText === '') {
+    // If no write operation has been performed, insert initial value
+    const clientsSize = currentYdoc.store.clients.size;
+    if (clientsSize === 0) {
       currentYdoc.getText('codemirror').insert(0, initialValue);
     }
 

+ 1 - 2
apps/app/src/stores/modal.tsx

@@ -4,10 +4,9 @@ import type {
   IAttachmentHasId, IPageToDeleteWithMeta, IPageToRenameWithMeta, IUserGroupHasId,
 } from '@growi/core';
 import { useSWRStatic } from '@growi/core/dist/swr';
+import { MarkdownTable } from '@growi/editor';
 import type { SWRResponse } from 'swr';
 
-
-import MarkdownTable from '~/client/models/MarkdownTable';
 import type { BookmarkFolderItems } from '~/interfaces/bookmark-info';
 import type {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction, onDeletedBookmarkFolderFunction, OnSelectedFunction,

+ 4 - 11
apps/app/src/styles/_editor.scss

@@ -1,3 +1,5 @@
+/* stylelint-disable selector-class-pattern */
+
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
 @use './variables' as var;
 @import './organisms/wiki-custom-sidebar';
@@ -72,8 +74,8 @@
 
     }
 
-    .page-editor-preview-container {
-    }
+    // .page-editor-preview-container {
+    // }
 
     .page-editor-preview-body {
       flex-grow: 1;
@@ -95,15 +97,6 @@
 
   }
 
-  // .builtin-editor .tab-pane#edit
-
-  /*****************
-   *     Toastr
-   *****************/
-  .Toastify .Toastify__toast-container {
-    top: 4.5em;
-  }
-
 }
 
 // TODO: Never used this id class

Некоторые файлы не были показаны из-за большого количества измененных файлов