Ver código fonte

Merge branch 'master' into fix/141984-146887-video-width

Tatsuya Ise 1 ano atrás
pai
commit
70a52a2002
86 arquivos alterados com 289 adições e 296 exclusões
  1. 1 0
      .eslintrc.js
  2. 18 1
      CHANGELOG.md
  3. 0 1
      apps/app/.eslintrc.js
  4. 1 1
      apps/app/docker/README.md
  5. 1 1
      apps/app/package.json
  6. 0 147
      apps/app/src/client/models/MarkdownTable.js
  7. 1 1
      apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts
  8. 1 1
      apps/app/src/components/Page/markdown-table-util-for-view.ts
  9. 15 10
      apps/app/src/components/PageControls/PageControls.tsx
  10. 1 1
      apps/app/src/components/PageEditor/HandsontableModal.tsx
  11. 1 1
      apps/app/src/components/PageEditor/LinkEditModal.tsx
  12. 1 1
      apps/app/src/components/PageEditor/MarkdownTableDataImportForm.tsx
  13. 1 2
      apps/app/src/components/PageEditor/markdown-table-util-for-editor.ts
  14. 1 2
      apps/app/src/stores/modal.tsx
  15. 1 1
      apps/slackbot-proxy/package.json
  16. 1 1
      package.json
  17. 20 2
      packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.module.scss
  18. 7 8
      packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx
  19. 3 3
      packages/editor/src/components/CodeMirrorEditor/Toolbar/AttachmentsDropdownItem.tsx
  20. 1 1
      packages/editor/src/components/CodeMirrorEditor/Toolbar/LinkEditButton.tsx
  21. 1 1
      packages/editor/src/components/CodeMirrorEditor/Toolbar/Toolbar.tsx
  22. 1 1
      packages/editor/src/components/CodeMirrorEditorMain.tsx
  23. 1 1
      packages/editor/src/components/CodeMirrorEditorReadOnly.tsx
  24. 2 2
      packages/editor/src/components/playground/Playground.tsx
  25. 4 3
      packages/editor/src/components/playground/PlaygroundController.tsx
  26. 2 1
      packages/editor/src/consts/editor-settings.ts
  27. 16 0
      packages/editor/src/consts/editor-themes.ts
  28. 2 0
      packages/editor/src/consts/index.ts
  29. 10 0
      packages/editor/src/consts/keymaps.ts
  30. 1 0
      packages/editor/src/index.ts
  31. 0 0
      packages/editor/src/models/index.ts
  32. 0 0
      packages/editor/src/models/markdown-table.d.ts
  33. 0 0
      packages/editor/src/models/markdown-table.js
  34. 0 0
      packages/editor/src/services-internal/editor-theme/.eslintrc.cjs
  35. 0 0
      packages/editor/src/services-internal/editor-theme/ayu.ts
  36. 0 0
      packages/editor/src/services-internal/editor-theme/cobalt.ts
  37. 0 0
      packages/editor/src/services-internal/editor-theme/eclipse.ts
  38. 3 18
      packages/editor/src/services-internal/editor-theme/index.ts
  39. 1 1
      packages/editor/src/services-internal/editor-theme/material.ts
  40. 1 1
      packages/editor/src/services-internal/editor-theme/nord.ts
  41. 0 0
      packages/editor/src/services-internal/editor-theme/original-dark.ts
  42. 1 1
      packages/editor/src/services-internal/editor-theme/original-light.ts
  43. 0 0
      packages/editor/src/services-internal/editor-theme/rose-pine.ts
  44. 0 0
      packages/editor/src/services-internal/extensions/emojiAutocompletionSettings.ts
  45. 2 0
      packages/editor/src/services-internal/extensions/index.ts
  46. 2 3
      packages/editor/src/services-internal/extensions/setDataLine.ts
  47. 0 0
      packages/editor/src/services-internal/file-dropzone/index.ts
  48. 19 0
      packages/editor/src/services-internal/file-dropzone/use-file-dropzone/FileDropzoneOverlay.tsx
  49. 2 2
      packages/editor/src/services-internal/file-dropzone/use-file-dropzone/use-file-dropzone.ts
  50. 8 0
      packages/editor/src/services-internal/index.ts
  51. 3 12
      packages/editor/src/services-internal/keymaps/index.ts
  52. 1 1
      packages/editor/src/services-internal/keymaps/vim.ts
  53. 1 1
      packages/editor/src/services-internal/link-util/Linker.ts
  54. 2 0
      packages/editor/src/services-internal/link-util/index.ts
  55. 1 1
      packages/editor/src/services-internal/link-util/markdown-link-util.ts
  56. 1 0
      packages/editor/src/services-internal/list-util/index.ts
  57. 1 1
      packages/editor/src/services-internal/list-util/insert-newline-continue-markup.ts
  58. 1 0
      packages/editor/src/services-internal/paste-util/index.ts
  59. 0 0
      packages/editor/src/services-internal/paste-util/paste-markdown-util.ts
  60. 2 0
      packages/editor/src/services-internal/table/index.ts
  61. 2 2
      packages/editor/src/services-internal/table/insert-new-row-to-table-markdown.ts
  62. 53 0
      packages/editor/src/services-internal/table/use-show-table-icon.ts
  63. 0 1
      packages/editor/src/services/codemirror-editor/index.ts
  64. 0 19
      packages/editor/src/services/file-dropzone/use-file-dropzone/FileDropzoneOverlay.tsx
  65. 1 4
      packages/editor/src/services/index.ts
  66. 1 0
      packages/editor/src/services/use-codemirror-editor/index.ts
  67. 4 3
      packages/editor/src/services/use-codemirror-editor/use-codemirror-editor.ts
  68. 3 2
      packages/editor/src/services/use-codemirror-editor/utils/append-extensions.ts
  69. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/focus.ts
  70. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/fold-drawio.ts
  71. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/get-doc.ts
  72. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/init-doc.ts
  73. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/insert-markdown-elements.ts
  74. 3 2
      packages/editor/src/services/use-codemirror-editor/utils/insert-prefix.ts
  75. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/insert-text.ts
  76. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/replace-text.ts
  77. 1 1
      packages/editor/src/services/use-codemirror-editor/utils/set-caret-line.ts
  78. 1 2
      packages/editor/src/stores/codemirror-editor.ts
  79. 1 1
      packages/editor/src/stores/use-collaborative-editor-mode.ts
  80. 3 2
      packages/editor/src/stores/use-default-extensions.ts
  81. 8 6
      packages/editor/src/stores/use-editor-settings.ts
  82. 1 1
      packages/editor/src/stores/use-handsontable.ts
  83. 2 2
      packages/editor/src/stores/use-link-edit-modal.ts
  84. 1 1
      packages/editor/src/stores/use-resolved-theme.ts
  85. 1 0
      packages/editor/svg/table.svg
  86. 28 3
      yarn.lock

+ 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: [

+ 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 - 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)

+ 1 - 1
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": "",

+ 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';

+ 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');

+ 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)) {

+ 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 {

+ 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,

+ 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 - 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,

+ 1 - 1
apps/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slackbot-proxy",
-  "version": "7.0.7-slackbot-proxy.0",
+  "version": "7.0.8-slackbot-proxy.0",
   "license": "MIT",
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "7.0.7-RC.0",
+  "version": "7.0.8-RC.0",
   "description": "Team collaboration software using markdown",
   "license": "MIT",
   "private": "true",

+ 20 - 2
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.module.scss

@@ -43,7 +43,6 @@
 
 }
 
-
 @mixin insertMaterialSymbolAndMessage($code, $message) {
   .overlay-icon:before {
     margin-right: 0.2em;
@@ -138,5 +137,24 @@
     }
     /* end of.dropzone */
   }
-}
 
+  .markdown-table-activated .cm-cursor {
+    &:after {
+      position: relative;
+      top: 0em;
+      left: 0.3em;
+      display: block;
+      width: 1em;
+      height: 1em;
+      content: ' ';
+      background-repeat: no-repeat;
+      background-size: 1em;
+    }
+  }
+
+  .markdown-table-activated .cm-cursor.cm-cursor-primary {
+    &:after {
+      background-image: url(../../../svg/table.svg);
+    }
+  }
+}

+ 7 - 8
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -1,6 +1,6 @@
+import type { DetailedHTMLProps } from 'react';
 import {
   forwardRef, useMemo, useRef, useEffect,
-  DetailedHTMLProps,
 } from 'react';
 
 import { indentUnit } from '@codemirror/language';
@@ -10,13 +10,11 @@ import {
 import { AcceptedUploadFileType } from '@growi/core';
 import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 
-import { EditorSettings, GlobalCodeMirrorEditorKey } from '../../consts';
+import type { EditorSettings, GlobalCodeMirrorEditorKey } from '../../consts';
 import {
   useFileDropzone, FileDropzoneOverlay,
-} from '../../services';
-import {
-  adjustPasteData, getStrFromBol,
-} from '../../services/paste-util/paste-markdown-util';
+  adjustPasteData, getStrFromBol, useShowTableIcon,
+} from '../../services-internal';
 import { useDefaultExtensions, useCodeMirrorEditorIsolated, useEditorSettings } from '../../stores';
 
 import { Toolbar } from './Toolbar';
@@ -74,6 +72,8 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
   useDefaultExtensions(codeMirrorEditor);
   useEditorSettings(codeMirrorEditor, editorSettings, onSave);
 
+  useShowTableIcon(codeMirrorEditor);
+
   useEffect(() => {
     if (indentSize == null) {
       return;
@@ -159,7 +159,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
   }, [onScroll, codeMirrorEditor]);
 
-
   const {
     getRootProps,
     getInputProps,
@@ -211,7 +210,7 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
   return (
     <div className={`${style['codemirror-editor']} flex-expand-vert overflow-y-hidden`}>
-      <div {...getRootProps()} className={`dropzone ${fileUploadState} flex-expand-vert`}>
+      <div {...getRootProps()} className={`dropzone  ${fileUploadState} flex-expand-vert`}>
         <input {...getInputProps()} />
         <FileDropzoneOverlay isEnabled={isDragActive} />
         <CodeMirrorEditorContainer ref={containerRef} />

+ 3 - 3
packages/editor/src/components/CodeMirrorEditor/Toolbar/AttachmentsDropdownItem.tsx

@@ -1,11 +1,11 @@
-import { ReactNode } from 'react';
+import type { ReactNode } from 'react';
 
-import { AcceptedUploadFileType } from '@growi/core';
+import type { AcceptedUploadFileType } from '@growi/core';
 import {
   DropdownItem,
 } from 'reactstrap';
 
-import { useFileDropzone } from '../../../services';
+import { useFileDropzone } from '../../../services-internal';
 
 type Props = {
   acceptedUploadFileType: AcceptedUploadFileType,

+ 1 - 1
packages/editor/src/components/CodeMirrorEditor/Toolbar/LinkEditButton.tsx

@@ -3,7 +3,7 @@ import { useCallback } from 'react';
 import { DropdownItem } from 'reactstrap';
 
 import type { GlobalCodeMirrorEditorKey } from '../../../consts';
-import { getMarkdownLink, replaceFocusedMarkdownLinkWithEditor } from '../../../services/link-util/markdown-link-util';
+import { getMarkdownLink, replaceFocusedMarkdownLinkWithEditor } from '../../../services-internal';
 import { useCodeMirrorEditorIsolated } from '../../../stores';
 import { useLinkEditModal } from '../../../stores/use-link-edit-modal';
 

+ 1 - 1
packages/editor/src/components/CodeMirrorEditor/Toolbar/Toolbar.tsx

@@ -1,6 +1,6 @@
 import { memo } from 'react';
 
-import { AcceptedUploadFileType } from '@growi/core';
+import type { AcceptedUploadFileType } from '@growi/core';
 
 import type { GlobalCodeMirrorEditorKey } from '../../../consts';
 

+ 1 - 1
packages/editor/src/components/CodeMirrorEditorMain.tsx

@@ -5,7 +5,7 @@ import { keymap, scrollPastEnd } from '@codemirror/view';
 import type { IUserHasId } from '@growi/core/dist/interfaces';
 
 import { GlobalCodeMirrorEditorKey } from '../consts';
-import { setDataLine } from '../services/extensions/setDataLine';
+import { setDataLine } from '../services-internal';
 import { useCodeMirrorEditorIsolated, useCollaborativeEditorMode } from '../stores';
 
 import { CodeMirrorEditor, type CodeMirrorEditorProps } from '.';

+ 1 - 1
packages/editor/src/components/CodeMirrorEditorReadOnly.tsx

@@ -3,7 +3,7 @@ import { useEffect } from 'react';
 import { type Extension, EditorState } from '@codemirror/state';
 
 import { GlobalCodeMirrorEditorKey } from '../consts';
-import { setDataLine } from '../services/extensions/setDataLine';
+import { setDataLine } from '../services-internal';
 import { useCodeMirrorEditorIsolated } from '../stores';
 
 import { CodeMirrorEditor } from '.';

+ 2 - 2
packages/editor/src/components/playground/Playground.tsx

@@ -5,8 +5,8 @@ import {
 import { AcceptedUploadFileType } from '@growi/core';
 import { toast } from 'react-toastify';
 
-import { EditorSettings, GlobalCodeMirrorEditorKey } from '../../consts';
-import type { EditorTheme, KeyMapMode } from '../../services';
+import { GlobalCodeMirrorEditorKey } from '../../consts';
+import type { EditorSettings, EditorTheme, KeyMapMode } from '../../consts';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 import { CodeMirrorEditorMain } from '../CodeMirrorEditorMain';
 

+ 4 - 3
packages/editor/src/components/playground/PlaygroundController.tsx

@@ -2,10 +2,11 @@ import { useCallback } from 'react';
 
 import { useForm } from 'react-hook-form';
 
-import { GlobalCodeMirrorEditorKey } from '../../consts';
+import type { EditorTheme, KeyMapMode } from '../../consts';
 import {
-  AllEditorTheme, AllKeyMap, EditorTheme, KeyMapMode,
-} from '../../services';
+  GlobalCodeMirrorEditorKey,
+  AllEditorTheme, AllKeyMap,
+} from '../../consts';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
 export const InitEditorValueRow = (): JSX.Element => {

+ 2 - 1
packages/editor/src/consts/editor-settings.ts

@@ -1,4 +1,5 @@
-import { EditorTheme, KeyMapMode } from '../services';
+import type { EditorTheme } from './editor-themes';
+import type { KeyMapMode } from './keymaps';
 
 export interface EditorSettings {
   theme: undefined | EditorTheme,

+ 16 - 0
packages/editor/src/consts/editor-themes.ts

@@ -0,0 +1,16 @@
+const EditorTheme = {
+  defaultlight: 'defaultlight',
+  eclipse: 'eclipse',
+  basic: 'basic',
+  ayu: 'ayu',
+  rosepine:  'rosepine',
+  defaultdark: 'defaultdark',
+  material: 'material',
+  nord: 'nord',
+  cobalt: 'cobalt',
+  kimbie: 'kimbie',
+} as const;
+
+export const DEFAULT_THEME = 'defaultlight';
+export const AllEditorTheme = Object.values(EditorTheme);
+export type EditorTheme = typeof EditorTheme[keyof typeof EditorTheme];

+ 2 - 0
packages/editor/src/consts/index.ts

@@ -1,3 +1,5 @@
 export * from './global-code-mirror-editor-key';
 export * from './ydoc-awareness-user-color';
 export * from './editor-settings';
+export * from './editor-themes';
+export * from './keymaps';

+ 10 - 0
packages/editor/src/consts/keymaps.ts

@@ -0,0 +1,10 @@
+const KeyMapMode = {
+  default: 'default',
+  vim: 'vim',
+  emacs: 'emacs',
+  vscode: 'vscode',
+} as const;
+
+export const DEFAULT_KEYMAP = 'default';
+export const AllKeyMap = Object.values(KeyMapMode);
+export type KeyMapMode = typeof KeyMapMode[keyof typeof KeyMapMode];

+ 1 - 0
packages/editor/src/index.ts

@@ -1,4 +1,5 @@
 export * from './components';
 export * from './consts';
+export * from './models';
 export * from './services';
 export * from './stores';

+ 0 - 0
packages/editor/src/services/table-util/index.ts → packages/editor/src/models/index.ts


+ 0 - 0
packages/editor/src/services/table-util/markdown-table.d.ts → packages/editor/src/models/markdown-table.d.ts


+ 0 - 0
packages/editor/src/services/table-util/markdown-table.js → packages/editor/src/models/markdown-table.js


+ 0 - 0
packages/editor/src/services/editor-theme/.eslintrc.cjs → packages/editor/src/services-internal/editor-theme/.eslintrc.cjs


+ 0 - 0
packages/editor/src/services/editor-theme/ayu.ts → packages/editor/src/services-internal/editor-theme/ayu.ts


+ 0 - 0
packages/editor/src/services/editor-theme/cobalt.ts → packages/editor/src/services-internal/editor-theme/cobalt.ts


+ 0 - 0
packages/editor/src/services/editor-theme/eclipse.ts → packages/editor/src/services-internal/editor-theme/eclipse.ts


+ 3 - 18
packages/editor/src/services/editor-theme/index.ts → packages/editor/src/services-internal/editor-theme/index.ts

@@ -1,4 +1,6 @@
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
+
+import type { EditorTheme } from '../../consts';
 
 export const getEditorTheme = async(themeName?: EditorTheme): Promise<Extension> => {
   switch (themeName) {
@@ -23,20 +25,3 @@ export const getEditorTheme = async(themeName?: EditorTheme): Promise<Extension>
   }
   return (await import('./original-light')).originalLight;
 };
-
-const EditorTheme = {
-  defaultlight: 'defaultlight',
-  eclipse: 'eclipse',
-  basic: 'basic',
-  ayu: 'ayu',
-  rosepine:  'rosepine',
-  defaultdark: 'defaultdark',
-  material: 'material',
-  nord: 'nord',
-  cobalt: 'cobalt',
-  kimbie: 'kimbie',
-} as const;
-
-export const DEFAULT_THEME = 'defaultlight';
-export const AllEditorTheme = Object.values(EditorTheme);
-export type EditorTheme = typeof EditorTheme[keyof typeof EditorTheme]

+ 1 - 1
packages/editor/src/services/editor-theme/material.ts → packages/editor/src/services-internal/editor-theme/material.ts

@@ -1,6 +1,6 @@
 // Ref: https://github.com/craftzdog/cm6-themes/blob/289d9e0ca6b500f4cdf68464f4f21dd8e2dd8963/packages/material-dark/src/index.ts
 import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
 import { EditorView } from '@codemirror/view';
 import { tags as t } from '@lezer/highlight';
 

+ 1 - 1
packages/editor/src/services/editor-theme/nord.ts → packages/editor/src/services-internal/editor-theme/nord.ts

@@ -1,7 +1,7 @@
 // Ref: https://github.com/craftzdog/cm6-themes/blob/221936c525dcfc05b298cc4d4a0ba284cb7c7138/packages/nord/src/index.ts
 
 import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
 import { EditorView } from '@codemirror/view';
 import { tags as t } from '@lezer/highlight';
 

+ 0 - 0
packages/editor/src/services/editor-theme/original-dark.ts → packages/editor/src/services-internal/editor-theme/original-dark.ts


+ 1 - 1
packages/editor/src/services/editor-theme/original-light.ts → packages/editor/src/services-internal/editor-theme/original-light.ts

@@ -1,6 +1,6 @@
 // Ref: https://github.com/uiwjs/react-codemirror/blob/bf3b862923d0cb04ccf4bb9da0791bdc7fd6d29b/themes/github/src/index.ts
 
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
 import { tags as t } from '@lezer/highlight';
 import { createTheme } from '@uiw/codemirror-themes';
 

+ 0 - 0
packages/editor/src/services/editor-theme/rose-pine.ts → packages/editor/src/services-internal/editor-theme/rose-pine.ts


+ 0 - 0
packages/editor/src/services/extensions/emojiAutocompletionSettings.ts → packages/editor/src/services-internal/extensions/emojiAutocompletionSettings.ts


+ 2 - 0
packages/editor/src/services-internal/extensions/index.ts

@@ -0,0 +1,2 @@
+export * from './emojiAutocompletionSettings';
+export * from './setDataLine';

+ 2 - 3
packages/editor/src/services/extensions/setDataLine.ts → packages/editor/src/services-internal/extensions/setDataLine.ts

@@ -3,9 +3,8 @@
 
 
 import { RangeSetBuilder } from '@codemirror/state';
-import {
-  EditorView, Decoration, ViewPlugin, DecorationSet, ViewUpdate,
-} from '@codemirror/view';
+import type { EditorView, DecorationSet, ViewUpdate } from '@codemirror/view';
+import { Decoration, ViewPlugin } from '@codemirror/view';
 
 const stripeDeco = (view: EditorView) => {
   const builder = new RangeSetBuilder<Decoration>();

+ 0 - 0
packages/editor/src/services/file-dropzone/index.ts → packages/editor/src/services-internal/file-dropzone/index.ts


+ 19 - 0
packages/editor/src/services-internal/file-dropzone/use-file-dropzone/FileDropzoneOverlay.tsx

@@ -0,0 +1,19 @@
+type Props = {
+  isEnabled: boolean,
+}
+
+export const FileDropzoneOverlay = (props: Props): JSX.Element => {
+  const { isEnabled } = props;
+
+  if (isEnabled) {
+    return (
+      <div className="overlay overlay-dropzone-active">
+        <span className="overlay-content">
+          <span className="overlay-icon material-symbols-outlined">
+          </span>
+        </span>
+      </div>
+    );
+  }
+  return <></>;
+};

+ 2 - 2
packages/editor/src/services/file-dropzone/use-file-dropzone/use-file-dropzone.ts → packages/editor/src/services-internal/file-dropzone/use-file-dropzone/use-file-dropzone.ts

@@ -1,8 +1,8 @@
 import { useCallback, useState } from 'react';
 
 import { AcceptedUploadFileType } from '@growi/core';
-import { useDropzone, Accept } from 'react-dropzone';
-import type { DropzoneOptions, DropzoneState } from 'react-dropzone';
+import { useDropzone } from 'react-dropzone';
+import type { DropzoneOptions, DropzoneState, Accept } from 'react-dropzone';
 
 
 type FileDropzoneState = DropzoneState & {

+ 8 - 0
packages/editor/src/services-internal/index.ts

@@ -0,0 +1,8 @@
+export * from './editor-theme';
+export * from './extensions';
+export * from './file-dropzone';
+export * from './keymaps';
+export * from './link-util';
+export * from './list-util';
+export * from './paste-util';
+export * from './table';

+ 3 - 12
packages/editor/src/services/keymaps/index.ts → packages/editor/src/services-internal/keymaps/index.ts

@@ -1,6 +1,8 @@
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
 import { keymap } from '@codemirror/view';
 
+import type { KeyMapMode } from '../../consts';
+
 
 export const getKeymap = async(keyMapName?: KeyMapMode, onSave?: () => void): Promise<Extension> => {
   switch (keyMapName) {
@@ -13,14 +15,3 @@ export const getKeymap = async(keyMapName?: KeyMapMode, onSave?: () => void): Pr
   }
   return keymap.of((await import('@codemirror/commands')).defaultKeymap);
 };
-
-const KeyMapMode = {
-  default: 'default',
-  vim: 'vim',
-  emacs: 'emacs',
-  vscode: 'vscode',
-} as const;
-
-export const DEFAULT_KEYMAP = 'default';
-export const AllKeyMap = Object.values(KeyMapMode);
-export type KeyMapMode = typeof KeyMapMode[keyof typeof KeyMapMode];

+ 1 - 1
packages/editor/src/services/keymaps/vim.ts → packages/editor/src/services-internal/keymaps/vim.ts

@@ -1,4 +1,4 @@
-import { Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
 import { Vim, vim } from '@replit/codemirror-vim';
 
 // vim useful keymap custom

+ 1 - 1
packages/editor/src/services/link-util/Linker.ts → packages/editor/src/services-internal/link-util/Linker.ts

@@ -1,6 +1,6 @@
 import { encodeSpaces } from '@growi/core/dist/utils/page-path-utils';
 
-export default class Linker {
+export class Linker {
 
   type: string;
 

+ 2 - 0
packages/editor/src/services-internal/link-util/index.ts

@@ -0,0 +1,2 @@
+export * from './Linker';
+export * from './markdown-link-util';

+ 1 - 1
packages/editor/src/services/link-util/markdown-link-util.ts → packages/editor/src/services-internal/link-util/markdown-link-util.ts

@@ -1,6 +1,6 @@
 import type { EditorView } from '@codemirror/view';
 
-import Linker from './Linker';
+import { Linker } from './Linker';
 
 const curPos = (editor: EditorView) => {
   return editor.state.selection.main.head;

+ 1 - 0
packages/editor/src/services-internal/list-util/index.ts

@@ -0,0 +1 @@
+export * from './insert-newline-continue-markup';

+ 1 - 1
packages/editor/src/services/list-util/insert-newline-continue-markup.ts → packages/editor/src/services-internal/list-util/insert-newline-continue-markup.ts

@@ -1,5 +1,5 @@
 import type { ChangeSpec } from '@codemirror/state';
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 // https://regex101.com/r/r9plEA/1
 const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]\s))(\s*)/;

+ 1 - 0
packages/editor/src/services-internal/paste-util/index.ts

@@ -0,0 +1 @@
+export * from './paste-markdown-util';

+ 0 - 0
packages/editor/src/services/paste-util/paste-markdown-util.ts → packages/editor/src/services-internal/paste-util/paste-markdown-util.ts


+ 2 - 0
packages/editor/src/services-internal/table/index.ts

@@ -0,0 +1,2 @@
+export * from './insert-new-row-to-table-markdown';
+export * from './use-show-table-icon';

+ 2 - 2
packages/editor/src/services/table-util/insert-new-row-to-table-markdown.ts → packages/editor/src/services-internal/table/insert-new-row-to-table-markdown.ts

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

+ 53 - 0
packages/editor/src/services-internal/table/use-show-table-icon.ts

@@ -0,0 +1,53 @@
+import { useEffect, useState } from 'react';
+
+import type { ViewUpdate } from '@codemirror/view';
+import { EditorView } from 'codemirror';
+
+
+import type { UseCodeMirrorEditor } from '../../services';
+
+import { isInTable } from './insert-new-row-to-table-markdown';
+
+const markdownTableActivatedClass = 'markdown-table-activated';
+
+export const useShowTableIcon = (codeMirrorEditor?: UseCodeMirrorEditor): void => {
+
+  const [editorClass, setEditorClass] = useState('');
+
+  const editor = codeMirrorEditor?.view;
+
+  useEffect(() => {
+
+    const handleFocusChanged = () => {
+      if (editor == null) {
+        return;
+      }
+      if (isInTable(editor)) {
+        setEditorClass(markdownTableActivatedClass);
+      }
+      else {
+        setEditorClass('');
+      }
+    };
+
+    const cleanupFunction = codeMirrorEditor?.appendExtensions(
+      EditorView.updateListener.of((v: ViewUpdate) => {
+        if (v.transactions.some(tr => tr.selection || tr.docChanged)) {
+          handleFocusChanged();
+        }
+      }),
+    );
+
+    return cleanupFunction;
+
+  }, [codeMirrorEditor, editor]);
+
+  useEffect(() => {
+    const cleanupFunction = codeMirrorEditor?.appendExtensions(
+      EditorView.editorAttributes.of({ class: editorClass }),
+    );
+
+    return cleanupFunction;
+  }, [codeMirrorEditor, editorClass]);
+
+};

+ 0 - 1
packages/editor/src/services/codemirror-editor/index.ts

@@ -1 +0,0 @@
-export * from './use-codemirror-editor/use-codemirror-editor';

+ 0 - 19
packages/editor/src/services/file-dropzone/use-file-dropzone/FileDropzoneOverlay.tsx

@@ -1,19 +0,0 @@
-type Props = {
-  isEnabled: boolean,
-}
-
-export const FileDropzoneOverlay = (props: Props) => {
-  const { isEnabled } = props;
-
-    if (isEnabled) {
-      return (
-        <div className="overlay overlay-dropzone-active">
-          <span className="overlay-content">
-            <span className="overlay-icon material-symbols-outlined">
-            </span>
-          </span>
-        </div>
-      );
-    }
-    return <></>;
-}

+ 1 - 4
packages/editor/src/services/index.ts

@@ -1,4 +1 @@
-export * from './codemirror-editor';
-export * from './file-dropzone';
-export * from './editor-theme';
-export * from './keymaps';
+export * from './use-codemirror-editor';

+ 1 - 0
packages/editor/src/services/use-codemirror-editor/index.ts

@@ -0,0 +1 @@
+export * from './use-codemirror-editor';

+ 4 - 3
packages/editor/src/services/codemirror-editor/use-codemirror-editor/use-codemirror-editor.ts → packages/editor/src/services/use-codemirror-editor/use-codemirror-editor.ts

@@ -1,15 +1,16 @@
 import { useMemo } from 'react';
 
-import {
+import type {
   EditorState,
 } from '@codemirror/state';
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 import { useCodeMirror, type UseCodeMirror } from '@uiw/react-codemirror';
 import deepmerge from 'ts-deepmerge';
 
 import { useAppendExtensions, type AppendExtensions } from './utils/append-extensions';
 import { useFocus, type Focus } from './utils/focus';
-import { FoldDrawio, useFoldDrawio } from './utils/fold-drawio';
+import type { FoldDrawio } from './utils/fold-drawio';
+import { useFoldDrawio } from './utils/fold-drawio';
 import { useGetDoc, type GetDoc } from './utils/get-doc';
 import { useInitDoc, type InitDoc } from './utils/init-doc';
 import { useInsertMarkdownElements, type InsertMarkdowElements } from './utils/insert-markdown-elements';

+ 3 - 2
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/append-extensions.ts → packages/editor/src/services/use-codemirror-editor/utils/append-extensions.ts

@@ -1,7 +1,8 @@
 import { useCallback } from 'react';
 
-import { Compartment, Extension, StateEffect } from '@codemirror/state';
-import { EditorView } from '@codemirror/view';
+import type { Extension } from '@codemirror/state';
+import { Compartment, StateEffect } from '@codemirror/state';
+import type { EditorView } from '@codemirror/view';
 
 type CleanupFunctions = () => void;
 export type AppendExtensions = (extensions: Extension | Extension[]) => CleanupFunctions | undefined;

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/focus.ts → packages/editor/src/services/use-codemirror-editor/utils/focus.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type Focus = () => void;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/fold-drawio.ts → packages/editor/src/services/use-codemirror-editor/utils/fold-drawio.ts

@@ -1,7 +1,7 @@
 import { useEffect } from 'react';
 
 import { foldEffect } from '@codemirror/language';
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type FoldDrawio = void;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/get-doc.ts → packages/editor/src/services/use-codemirror-editor/utils/get-doc.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type GetDoc = () => string;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/init-doc.ts → packages/editor/src/services/use-codemirror-editor/utils/init-doc.ts

@@ -1,7 +1,7 @@
 import { useCallback } from 'react';
 
 import { Transaction } from '@codemirror/state';
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type InitDoc = (doc?: string) => void;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/insert-markdown-elements.ts → packages/editor/src/services/use-codemirror-editor/utils/insert-markdown-elements.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type InsertMarkdowElements = (
   prefix: string,

+ 3 - 2
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/insert-prefix.ts → packages/editor/src/services/use-codemirror-editor/utils/insert-prefix.ts

@@ -1,6 +1,7 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { ChangeSpec } from '@codemirror/state';
+import type { EditorView } from '@codemirror/view';
 
 export type InsertPrefix = (prefix: string, noSpaceIfPrefixExists?: boolean) => void;
 
@@ -16,7 +17,7 @@ export const useInsertPrefix = (view?: EditorView): InsertPrefix => {
     const endLine = view.state.doc.lineAt(to);
 
     // Insert prefix for each line
-    const lines = [];
+    const lines: ChangeSpec[] = [];
     let insertTextLength = 0;
     for (let i = startLine.number; i <= endLine.number; i++) {
       const line = view.state.doc.line(i);

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/insert-text.ts → packages/editor/src/services/use-codemirror-editor/utils/insert-text.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type InsertText = (text: string) => void;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/replace-text.ts → packages/editor/src/services/use-codemirror-editor/utils/replace-text.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type ReplaceText = (text: string) => void;
 

+ 1 - 1
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/set-caret-line.ts → packages/editor/src/services/use-codemirror-editor/utils/set-caret-line.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 export type SetCaretLine = (lineNumber?: number) => void;
 

+ 1 - 2
packages/editor/src/stores/codemirror-editor.ts

@@ -5,8 +5,7 @@ import type { ReactCodeMirrorProps, UseCodeMirror } from '@uiw/react-codemirror'
 import type { SWRResponse } from 'swr';
 import deepmerge from 'ts-deepmerge';
 
-import type { UseCodeMirrorEditor } from '../services';
-import { useCodeMirrorEditor } from '../services';
+import { type UseCodeMirrorEditor, useCodeMirrorEditor } from '../services';
 
 
 const isValid = (u: UseCodeMirrorEditor) => {

+ 1 - 1
packages/editor/src/stores/use-collaborative-editor-mode.ts

@@ -8,7 +8,7 @@ import { SocketIOProvider } from 'y-socket.io';
 import * as Y from 'yjs';
 
 import { userColor } from '../consts';
-import { UseCodeMirrorEditor } from '../services';
+import type { UseCodeMirrorEditor } from '../services';
 
 type UserLocalState = {
   name: string;

+ 3 - 2
packages/editor/src/stores/use-default-extensions.ts

@@ -7,11 +7,12 @@ import { languages } from '@codemirror/language-data';
 import {
   Prec, type Extension,
 } from '@codemirror/state';
-import { keymap, EditorView, KeyBinding } from '@codemirror/view';
+import type { KeyBinding } from '@codemirror/view';
+import { keymap, EditorView } from '@codemirror/view';
 import { tags } from '@lezer/highlight';
 
 import type { UseCodeMirrorEditor } from '../services';
-import { emojiAutocompletionSettings } from '../services/extensions/emojiAutocompletionSettings';
+import { emojiAutocompletionSettings } from '../services-internal';
 
 
 // set new markdownKeymap instead of default one

+ 8 - 6
packages/editor/src/stores/use-editor-settings.ts

@@ -1,15 +1,17 @@
 import { useEffect, useCallback, useState } from 'react';
 
-import { Prec, Extension } from '@codemirror/state';
+import type { Extension } from '@codemirror/state';
+import { Prec } from '@codemirror/state';
 import {
   keymap, type Command, highlightActiveLine, highlightActiveLineGutter,
 } from '@codemirror/view';
 
-import type { EditorSettings } from '../consts';
-import type { UseCodeMirrorEditor, EditorTheme, KeyMapMode } from '../services';
-import { getEditorTheme, getKeymap } from '../services';
-import { insertNewlineContinueMarkup } from '../services/list-util/insert-newline-continue-markup';
-import { insertNewRowToMarkdownTable, isInTable } from '../services/table-util/insert-new-row-to-table-markdown';
+import type { EditorSettings, KeyMapMode, EditorTheme } from '../consts';
+import type { UseCodeMirrorEditor } from '../services';
+import {
+  getEditorTheme, getKeymap, insertNewlineContinueMarkup, insertNewRowToMarkdownTable, isInTable,
+} from '../services-internal';
+
 
 export const useEditorSettings = (
     codeMirrorEditor?: UseCodeMirrorEditor,

+ 1 - 1
packages/editor/src/stores/use-handsontable.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 import { useSWRStatic } from '@growi/core/dist/swr';
 import type { SWRResponse } from 'swr';
 

+ 2 - 2
packages/editor/src/stores/use-link-edit-modal.ts

@@ -1,7 +1,7 @@
 import { useSWRStatic } from '@growi/core/dist/swr';
-import { SWRResponse } from 'swr';
+import type { SWRResponse } from 'swr';
 
-import Linker from '../services/link-util/Linker';
+import type { Linker } from '../services-internal';
 
 type LinkEditModalStatus = {
   isOpened: boolean,

+ 1 - 1
packages/editor/src/stores/use-resolved-theme.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { ColorScheme } from '@growi/core';
+import type { ColorScheme } from '@growi/core';
 import { useSWRStatic } from '@growi/core/dist/swr';
 import type { SWRResponse } from 'swr';
 import { mutate } from 'swr';

+ 1 - 0
packages/editor/svg/table.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="203" height="160" viewBox="0 0 20.3 16"><path d="M19.1 16H1.2A1.2 1.2 0 0 1 0 14.8V1.2A1.2 1.2 0 0 1 1.2 0h17.9a1.2 1.2 0 0 1 1.2 1.2v13.6a1.2 1.2 0 0 1-1.2 1.2zm-5.2-4.3v3.2h5.3v-3.2zm-6.4 0v3.2h5.3v-3.2zm-6.4 0v3.2h5.3v-3.2zm12.8-4.2v3.2h5.3V7.5zm-6.4 0v3.2h5.3V7.5zm-6.4 0v3.2h5.3V7.5zm12.8-4.3v3.2h5.3V3.2zm-6.4 0v3.2h5.3V3.2zm-6.4 0v3.2h5.3V3.2z"/></svg>

+ 28 - 3
yarn.lock

@@ -17279,7 +17279,7 @@ string-template@>=1.0.0:
   resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96"
   integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y=
 
-"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -17297,6 +17297,15 @@ string-width@=4.2.2:
     is-fullwidth-code-point "^3.0.0"
     strip-ansi "^6.0.0"
 
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
 string-width@^5.0.1, string-width@^5.1.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
@@ -17380,7 +17389,7 @@ stringify-entities@^4.0.0:
     character-entities-html4 "^2.0.0"
     character-entities-legacy "^3.0.0"
 
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -17394,6 +17403,13 @@ strip-ansi@^3.0.0:
   dependencies:
     ansi-regex "^2.0.0"
 
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 strip-ansi@^7.0.1, strip-ansi@^7.1.0:
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -19225,7 +19241,7 @@ word-wrap@^1.2.3:
   resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
   integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
 
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
   integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -19243,6 +19259,15 @@ wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"