Yuki Takei 3 лет назад
Родитель
Сommit
388114dc61

+ 0 - 2
.github/workflows/ci-app-prod.yml

@@ -13,7 +13,6 @@ on:
       - yarn.lock
       - apps/app/**
       - '!apps/app/docker/**'
-      - packages/codemirror-textlint/**
       - packages/core/**
       - packages/preset-themes/**
       - packages/presentation/**
@@ -33,7 +32,6 @@ on:
       - turbo.json
       - apps/app/**
       - '!apps/app/docker/**'
-      - packages/codemirror-textlint/**
       - packages/core/**
       - packages/preset-themes/**
       - packages/remark-*/**

+ 0 - 1
.github/workflows/ci-app.yml

@@ -13,7 +13,6 @@ on:
       - yarn.lock
       - apps/app/**
       - '!apps/app/docker/**'
-      - packages/codemirror-textlint/**
       - packages/core/**
       - packages/hackmd/**
       - packages/presentation/**

+ 0 - 1
apps/app/jest.config.js

@@ -4,7 +4,6 @@
 const MODULE_NAME_MAPPING = {
   '^\\^/(.+)$': '<rootDir>/$1',
   '^~/(.+)$': '<rootDir>/src/$1',
-  '^@growi/codemirror-textlint$': '<rootDir>/../../packages/codemirror-textlint/src',
   '^@growi/remark-drawio$': '<rootDir>/../../packages/remark-drawio/src',
   '^@growi/remark-growi-directive$': '<rootDir>/../../packages/remark-growi-directive/src',
 };

+ 1 - 40
apps/app/public/static/locales/en_US/translation.json

@@ -243,41 +243,7 @@
     }
   },
   "editor_settings": {
-    "editor_settings": "Editor Settings",
-    "common_settings": {
-      "common_settings": "Common Settings",
-      "common_misspellings": "Textlint rules to find common misspellings from Wikipedia.",
-      "max_comma": "Textlint rule is that limit maximum ten(,) count of sentence. Default: 4",
-      "sentence_length": "Textlint rules that limit Maximum Length of Sentence. Default: 100",
-      "en_capitalization": "Textlint rule that check capitalization in english text.",
-      "no_unmatched_pair": "Textlint rule that check unmatched pairs like ( and ]",
-      "date_weekday_mismatch": "Textlint rule that found mismatch between date and weekday.",
-      "no_kangxi_radicals": "Textlint rule to prevent using kangxi radicals.",
-      "no_surrogate_pair": "Detects surrogate pairs (D800-DBFF and DC00-DFFF) in sentences.",
-      "no_zero_width_spaces": "Textlint rule that disallow zero width spaces.",
-      "period_in_list_item": "Textlint rule that check with or without period in list item.",
-      "use_si_units": "Use of units other than SI unit units is prohibited."
-
-      },
-    "japanese_settings": {
-      "japanese_settings": "Japanese Settings",
-      "ja_no_abusage": "Textlint rules to check for common misuse.",
-      "ja_hiragana_keishikimeishi": "Textlint rules to check easy-to-read Keishikimeishi(pronouns) written in Hiragana than Kanji.",
-      "ja_no_inappropriate_words": "Textlint rules to check for inappropriate expressions",
-      "ja_no_mixed_period": "Textlint rules to check that a paragraph always has a punctuation mark at the end.",
-      "ja_no_redundant_expression": "Textlint rules that prohibits redundant expressions. Redundant expressions are expressions that make sense even if they are omitted from the sentence.",
-      "max_kanji_continuous_len": "Textlint rules that limits the maximum number of consecutive Kanji. Default: 5",
-      "max_ten": "Textlint rule is that limit maximum ten(、) count of sentence.",
-      "no_double_negative_ja": "Textlint rules that detects double negation.",
-      "no_doubled_conjunction": "Textlint rules to check duplicated same conjunctions.",
-      "no_doubled_joshi": "Textlint rules that checks that the same particle appears consecutively in one sentence.",
-      "no_dropping_the_ra": "Textlint rules that detects the word dropping the ra.",
-      "no_hankaku_kana": "Textlint rules that disallow to use Half-width kana.",
-      "prefer_tari_tari": "Textlint rules that checks tari tari.",
-      "ja_unnatural_alphabet": "Detects unnatural alphabets.",
-      "no_mixed_zenkaku_and_hankaku_alphabet": "Check for mixed full-width and half-width alphabets.",
-      "no_nfd": "textlint rule that disallow to use NFD like UTF8-MAC Sonant mark."
-    }
+    "editor_settings": "Editor Settings"
   },
   "search_help": {
     "title": "Searching Help",
@@ -440,11 +406,6 @@
       "Post": "Post"
     }
   },
-  "modal_enable_textlint": {
-    "confirm_download_dict_and_enable_textlint": "Are you sure you want to enable Textlint? This will download 20MB of dictionary file.",
-    "enable_textlint": "Enable Textlint",
-    "dont_ask_again": "Don't ask again"
-  },
   "modal_resolve_conflict": {
     "file_conflicting_with_newer_remote": "This file is conflicting with newer remote file",
     "resolve_conflict_message": "Please select page body",

+ 0 - 5
apps/app/public/static/locales/ja_JP/translation.json

@@ -440,11 +440,6 @@
       "Post": "投稿"
     }
   },
-  "modal_enable_textlint": {
-    "confirm_download_dict_and_enable_textlint": "Textlintを有効にしますか?20MBの辞書ファイルをダウンロードします。",
-    "enable_textlint": "Textlintを有効にする",
-    "dont_ask_again": "常に許可する"
-  },
   "modal_resolve_conflict": {
     "file_conflicting_with_newer_remote": "サーバー側の新しいファイルと衝突します。",
     "resolve_conflict_message": "ページ本文を選んでください",

+ 1 - 39
apps/app/public/static/locales/zh_CN/translation.json

@@ -235,40 +235,7 @@
     }
   },
   "editor_settings": {
-    "editor_settings": "编辑器设置",
-    "common_settings": {
-      "common_settings": "常用设置",
-      "common_misspellings": "从 Wikipedia 中查找常见拼写错误的 Textlint。",
-      "max_comma": "Textlint 规则是限制句子的最大十(,)个计数。默认:4。",
-      "sentence_length": "限制最大句子长度的 Textlint 默认: 100。",
-      "en_capitalization": "检查英文文本大小写的 Textlint 规则。",
-      "no_unmatched_pair": "检查不匹配对的 Textlint 规则,如 ( 和 ]",
-      "date_weekday_mismatch": "发现日期和工作日之间不匹配的 Textlint 规则。",
-      "no_kangxi_radicals": "防止使用康熙部首的 Textlint 规则。",
-      "no_surrogate_pair": "检测句子中的代理对(D800-DBFF 和 DC00-DFFF)。",
-      "no_zero_width_spaces": "不允许零宽度空格的 Textlint 规则。",
-      "period_in_list_item": "在列表项中检查是否有句点的 Textlint 规则。",
-      "use_si_units": "禁止使用 SI 单位以外的单位。"
-      },
-    "japanese_settings": {
-      "japanese_settings": "日语设置",
-      "ja_no_abusage": "用于检查常见误用的 Textlint 规则。",
-      "ja_hiragana_keishikimeishi": "Textlint 规则检查易于阅读的 Keishikimeishi(代词)用平假名而不是汉字编写。",
-      "ja_no_inappropriate_words": "Textlint 规则来检查不适当的表达",
-      "ja_no_mixed_period": "Textlint 规则用于检查段落末尾是否总是有标点符号。",
-      "ja_no_redundant_expression": "禁止冗余表达式的 Textlint 规则。冗余表达式是即使从句子中省略也有意义的表达式。",
-      "max_kanji_continuous_len": "限制连续汉字的最大数量的 Textlint 规则。默认:5。",
-      "max_ten": "Textlint 规则是限制句子的最大十(、)个计数。",
-      "no_double_negative_ja": "检测双重否定的 Textlint 规则。",
-      "no_doubled_conjunction": "Textlint 规则来检查重复的相同连词。",
-      "no_doubled_joshi": "Textlint 规则,用于检查同一个粒子是否连续出现在一个句子中。",
-      "no_dropping_the_ra": "检测丢弃 ra 的单词的 Textlint 规则。",
-      "no_hankaku_kana": "不允许使用半角假名的 Textlint 规则。",
-      "prefer_tari_tari": "检查 tari tari 的 Textlint 规则。",
-      "ja_unnatural_alphabet": "检测不自然的字母。",
-      "no_mixed_zenkaku_and_hankaku_alphabet": "检查混合的全角和半角字母。",
-      "no_nfd": "禁止使用 UTF8-MAC 浊音等 NFD。"
-    }
+    "editor_settings": "编辑器设置"
   },
 	"search_help": {
 		"title": "搜索帮助",
@@ -429,11 +396,6 @@
 			"Post": "提交"
 		}
 	},
-  "modal_enable_textlint": {
-    "confirm_download_dict_and_enable_textlint": "您确定要启用 Textlint 吗?这将下载 20MB 的字典文件。",
-    "enable_textlint": "启用Textlint",
-    "dont_ask_again": "不要再问"
-  },
   "modal_resolve_conflict": {
     "file_conflicting_with_newer_remote": "此文件与较新的远程文件冲突",
     "resolve_conflict_message": "选择页面正文",

+ 17 - 261
apps/app/src/components/Me/EditorSettings.tsx

@@ -1,273 +1,28 @@
-import React, {
-  Dispatch, memo,
-  FC, SetStateAction, useCallback, useEffect, useState,
-  useMemo,
-} from 'react';
-
-import { useTranslation } from 'next-i18next';
-
-import { toastSuccess, toastError } from '~/client/util/toastr';
-import { useEditorSettings } from '~/stores/editor';
-
-
-type EditorSettingsBodyProps = Record<string, never>;
-
-type RuleListGroupProps = {
-  title: string;
-  ruleList: RulesMenuItem[]
-  textlintRules: LintRule[]
-  setTextlintRules: Dispatch<SetStateAction<LintRule[]>>
-}
-
-type LintRule = {
-  name: string
-  options?: unknown
-  isEnabled?: boolean
-}
-
-type RulesMenuItem = {
-  name: string
-  description: string
-}
-
-
-const commonRulesMenuItems = [
-  {
-    name: 'common-misspellings',
-    description: 'editor_settings.common_settings.common_misspellings',
-  },
-  {
-    name: 'max-comma',
-    description: 'editor_settings.common_settings.max_comma',
-  },
-  {
-    name: 'sentence-length',
-    description: 'editor_settings.common_settings.sentence_length',
-  },
-  // {  // omit because en-pos package is too big
-  //   name: 'en-capitalization',
-  //   description: 'editor_settings.common_settings.en_capitalization',
-  // },
-  {
-    name: 'no-unmatched-pair',
-    description: 'editor_settings.common_settings.no_unmatched_pair',
-  },
-  {
-    name: 'date-weekday-mismatch',
-    description: 'editor_settings.common_settings.date_weekday_mismatch',
-  },
-  {
-    name: 'no-kangxi-radicals',
-    description: 'editor_settings.common_settings.no_kangxi_radicals',
-  },
-  {
-    name: 'no-surrogate-pair',
-    description: 'editor_settings.common_settings.no_surrogate_pair',
-  },
-  {
-    name: 'no-zero-width-spaces',
-    description: 'editor_settings.common_settings.no_zero_width_spaces',
-  },
-  {
-    name: 'period-in-list-item',
-    description: 'editor_settings.common_settings.period_in_list_item',
-  },
-  {
-    name: 'use-si-units',
-    description: 'editor_settings.common_settings.use_si_units',
-  },
-];
-
-const japaneseRulesMenuItems = [
-  {
-    name: 'ja-hiragana-keishikimeishi',
-    description: 'editor_settings.japanese_settings.ja_hiragana_keishikimeishi',
-  },
-  {
-    name: 'ja-no-abusage',
-    description: 'editor_settings.japanese_settings.ja_no_abusage',
-  },
-  {
-    name: 'ja-no-inappropriate-words',
-    description: 'editor_settings.japanese_settings.ja_no_inappropriate_words',
-  },
-  {
-    name: 'ja-no-mixed-period',
-    description: 'editor_settings.japanese_settings.ja_no_mixed_period',
-  },
-  {
-    name: 'ja-no-redundant-expression',
-    description: 'editor_settings.japanese_settings.ja_no_redundant_expression',
-  },
-  {
-    name: 'max-kanji-continuous-len',
-    description: 'editor_settings.japanese_settings.max_kanji_continuous_len',
-  },
-  {
-    name: 'max-ten',
-    description: 'editor_settings.japanese_settings.max_ten',
-  },
-  {
-    name: 'no-double-negative-ja',
-    description: 'editor_settings.japanese_settings.no_double_negative_ja',
-  },
-  {
-    name: 'no-doubled-conjunction',
-    description: 'editor_settings.japanese_settings.no_doubled_conjunction',
-  },
-  {
-    name: 'no-doubled-joshi',
-    description: 'editor_settings.japanese_settings.no_doubled_joshi',
-  },
-  {
-    name: 'no-dropping-the-ra',
-    description: 'editor_settings.japanese_settings.no_dropping_the_ra',
-  },
-  {
-    name: 'no-hankaku-kana',
-    description: 'editor_settings.japanese_settings.no_hankaku_kana',
-  },
-  {
-    name: 'prefer-tari-tari',
-    description: 'editor_settings.japanese_settings.prefer_tari_tari',
-  },
-  {
-    name: 'ja-unnatural-alphabet',
-    description: 'editor_settings.japanese_settings.ja_unnatural_alphabet',
-  },
-  {
-    name: 'no-mixed-zenkaku-and-hankaku-alphabet',
-    description: 'editor_settings.japanese_settings.no_mixed_zenkaku_and_hankaku_alphabet',
-  },
-  {
-    name: 'no-nfd',
-    description: 'editor_settings.japanese_settings.no_nfd',
-  },
-
-];
-
-
-const RuleListGroup: FC<RuleListGroupProps> = ({
-  title, ruleList, textlintRules, setTextlintRules,
-}: RuleListGroupProps) => {
-  const { t } = useTranslation();
-
-  const isCheckedRule = (ruleName: string) => (
-    textlintRules.find(stateRule => (
-      stateRule.name === ruleName
-    ))?.isEnabled || false
-  );
-
-  const ruleCheckboxHandler = (isChecked: boolean, ruleName: string) => {
-    setTextlintRules(prevState => (
-      prevState.filter(rule => rule.name !== ruleName).concat({ name: ruleName, isEnabled: isChecked })
-    ));
-  };
-
-  return (
-    <>
-      <h2 className="border-bottom my-4">{t(title)}</h2>
-      <div className="form-group row">
-        <div className="offset-md-3 col-md-6 text-left">
-          {ruleList.map(rule => (
-            <div
-              key={rule.name}
-              className="custom-control custom-switch custom-checkbox-success"
-            >
-              <input
-                type="checkbox"
-                className="custom-control-input"
-                id={rule.name}
-                checked={isCheckedRule(rule.name)}
-                onChange={e => ruleCheckboxHandler(e.target.checked, rule.name)}
-              />
-              <label className="custom-control-label" htmlFor={rule.name}>
-                <strong>{rule.name}</strong>
-              </label>
-              <p className="form-text text-muted small">
-                {t(rule.description)}
-              </p>
-            </div>
-          ))}
-        </div>
-      </div>
-    </>
-  );
-};
-
-const createRulesFromDefaultList = (rule: { name: string }) => (
-  {
-    name: rule.name,
-    isEnabled: true,
-  }
-);
-
+import { memo } from 'react';
 
 export const EditorSettings = memo((): JSX.Element => {
-  const { t } = useTranslation();
-  const [textlintRules, setTextlintRules] = useState<LintRule[]>([]);
+  // const { t } = useTranslation();
 
-  const { data: dataEditorSettings, update: updateEditorSettings } = useEditorSettings();
+  // const { data: dataEditorSettings, update: updateEditorSettings } = useEditorSettings();
 
-  const defaultRules = useMemo(() => {
-    const defaultCommonRules = commonRulesMenuItems.map(rule => createRulesFromDefaultList(rule));
-    const defaultJapaneseRules = japaneseRulesMenuItems.map(rule => createRulesFromDefaultList(rule));
+  // const updateRulesHandler = useCallback(async() => {
+  //   try {
+  //     await updateEditorSettings({ textlintSettings: { textlintRules } });
+  //     toastSuccess(t('toaster.update_successed', { target: 'Updated Textlint Settings', ns: 'commons' }));
+  //   }
+  //   catch (err) {
+  //     toastError(err);
+  //   }
+  // }, [t, textlintRules, updateEditorSettings]);
 
-    return [...defaultCommonRules, ...defaultJapaneseRules];
-  }, []);
-
-  const initializeEditorSettings = useCallback(() => {
-    if (dataEditorSettings == null) {
-      return;
-    }
-
-    const retrievedRules: LintRule[] | undefined = dataEditorSettings?.textlintSettings?.textlintRules;
-
-    // If database is empty, add default rules to state
-    if (retrievedRules != null && retrievedRules.length > 0) {
-      setTextlintRules(retrievedRules);
-      return;
-    }
-    setTextlintRules(defaultRules);
-  }, [dataEditorSettings, defaultRules]);
-
-  const updateRulesHandler = useCallback(async() => {
-    try {
-      await updateEditorSettings({ textlintSettings: { textlintRules } });
-      toastSuccess(t('toaster.update_successed', { target: 'Updated Textlint Settings', ns: 'commons' }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }, [t, textlintRules, updateEditorSettings]);
-
-  useEffect(() => {
-    initializeEditorSettings();
-  }, [initializeEditorSettings]);
-
-  if (textlintRules == null) {
-    return (
-      <div className="text-muted text-center">
-        <i className="fa fa-2x fa-spinner fa-pulse"></i>
-      </div>
-    );
-  }
+  // useEffect(() => {
+  //   initializeEditorSettings();
+  // }, [initializeEditorSettings]);
 
   return (
     <div data-testid="grw-editor-settings">
-      <RuleListGroup
-        title="editor_settings.common_settings.common_settings"
-        ruleList={commonRulesMenuItems}
-        textlintRules={textlintRules}
-        setTextlintRules={setTextlintRules}
-      />
-      <RuleListGroup
-        title="editor_settings.japanese_settings.japanese_settings"
-        ruleList={japaneseRulesMenuItems}
-        textlintRules={textlintRules}
-        setTextlintRules={setTextlintRules}
-      />
 
+      {/*
       <div className="row my-3">
         <div className="offset-4 col-5">
           <button
@@ -280,6 +35,7 @@ export const EditorSettings = memo((): JSX.Element => {
           </button>
         </div>
       </div>
+      */}
     </div>
   );
 });

+ 7 - 8
apps/app/src/components/Me/PersonalSettings.jsx

@@ -1,13 +1,12 @@
 
 import React, { useMemo } from 'react';
 
-import PropTypes from 'prop-types';
 import { useTranslation } from 'next-i18next';
 
 import CustomNavAndContents from '../CustomNavigation/CustomNavAndContents';
 
 import ApiSettings from './ApiSettings';
-import { EditorSettings } from './EditorSettings';
+// import { EditorSettings } from './EditorSettings';
 import ExternalAccountLinkedMe from './ExternalAccountLinkedMe';
 import InAppNotificationSettings from './InAppNotificationSettings';
 import PasswordSettings from './PasswordSettings';
@@ -43,12 +42,12 @@ const PersonalSettings = () => {
         i18n: t('API Settings'),
         index: 3,
       },
-      editor_settings: {
-        Icon: () => <i className="icon-fw icon-pencil"></i>,
-        Content: EditorSettings,
-        i18n: t('editor_settings.editor_settings'),
-        index: 4,
-      },
+      // editor_settings: {
+      //   Icon: () => <i className="icon-fw icon-pencil"></i>,
+      //   Content: EditorSettings,
+      //   i18n: t('editor_settings.editor_settings'),
+      //   index: 4,
+      // },
       in_app_notification_settings: {
         Icon: () => <i className="icon-fw icon-bell"></i>,
         Content: InAppNotificationSettings,

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

@@ -25,7 +25,7 @@ import {
   useIsEditable, useIsUploadableFile, useIsUploadableImage, useIsIndentSizeForced,
 } from '~/stores/context';
 import {
-  useCurrentIndentSize, useIsSlackEnabled, useIsTextlintEnabled, usePageTagsForEditors,
+  useCurrentIndentSize, useIsSlackEnabled, usePageTagsForEditors,
   useIsEnabledUnsavedWarning,
   useIsConflict,
   useEditingMarkdown,
@@ -91,7 +91,6 @@ const PageEditor = React.memo((): JSX.Element => {
   const { data: isEditable } = useIsEditable();
   const { data: editorMode, mutate: mutateEditorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
-  const { data: isTextlintEnabled } = useIsTextlintEnabled();
   const { data: isIndentSizeForced } = useIsIndentSizeForced();
   const { data: currentIndentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
   const { data: isUploadableFile } = useIsUploadableFile();
@@ -528,7 +527,6 @@ const PageEditor = React.memo((): JSX.Element => {
           value={initialValue}
           isUploadable={isUploadable}
           isUploadableFile={isUploadableFile}
-          isTextlintEnabled={isTextlintEnabled}
           indentSize={currentIndentSize}
           onScroll={editorScrolledHandler}
           onScrollCursorIntoView={editorScrollCursorIntoViewHandler}

+ 0 - 30
apps/app/src/components/PageEditor/CodeMirrorEditor.jsx

@@ -1,8 +1,6 @@
 import React, { useCallback, memo } from 'react';
 
-import { createValidator } from '@growi/codemirror-textlint';
 import { commands } from 'codemirror';
-import { JSHINT } from 'jshint';
 import * as loadCssSync from 'load-css-file';
 import PropTypes from 'prop-types';
 import { Button } from 'reactstrap';
@@ -36,10 +34,6 @@ import SimpleCheatsheet from './SimpleCheatsheet';
 
 import styles from './CodeMirrorEditor.module.scss';
 
-// Textlint
-window.JSHINT = JSHINT;
-window.kuromojin = { dicPath: '/static/dict' };
-
 require('codemirror/addon/hint/show-hint.css'); // Import from CodeMirrorEditor.module.scss not working
 require('codemirror/addon/display/placeholder');
 require('codemirror/addon/edit/matchbrackets');
@@ -57,7 +51,6 @@ require('codemirror/addon/fold/foldgutter');
 require('codemirror/addon/fold/markdown-fold');
 require('codemirror/addon/fold/brace-fold');
 require('codemirror/addon/display/placeholder');
-require('codemirror/addon/lint/lint');
 require('~/client/util/codemirror/autorefresh.ext');
 require('~/client/util/codemirror/drawio-fold.ext');
 require('~/client/util/codemirror/gfm-growi.mode');
@@ -208,8 +201,6 @@ class CodeMirrorEditor extends AbstractEditor {
   componentWillReceiveProps(nextProps) {
     this.initializeEditorSettings(nextProps.editorSettings);
 
-    this.initializeTextlint(nextProps.isTextlintEnabled, nextProps.editorSettings);
-
     // fold drawio section
     this.foldDrawioSection();
   }
@@ -232,19 +223,6 @@ class CodeMirrorEditor extends AbstractEditor {
     }
   }
 
-  async initializeTextlint(isTextlintEnabled, editorSettings) {
-    if (!isTextlintEnabled || editorSettings == null) {
-      return;
-    }
-
-    const textlintRules = editorSettings.textlintSettings?.textlintRules;
-
-    // If database has empty array, pass null instead to enable all default rules
-    const rulesForValidator = (textlintRules == null || textlintRules.length === 0) ? null : textlintRules;
-    this.textlintValidator = createValidator(rulesForValidator);
-    this.codemirrorLintConfig = { getAnnotations: this.textlintValidator, async: true };
-  }
-
   getCodeMirror() {
     return this.cm.current?.editor;
   }
@@ -1071,9 +1049,6 @@ class CodeMirrorEditor extends AbstractEditor {
 
 
   render() {
-    const { isTextlintEnabled } = this.props;
-
-    const lint = isTextlintEnabled ? this.codemirrorLintConfig : false;
     const additionalClasses = Array.from(this.state.additionalClassSet).join(' ');
     const placeholder = this.state.isGfmMode ? 'Input with Markdown..' : 'Input with Plain Text..';
 
@@ -1081,9 +1056,6 @@ class CodeMirrorEditor extends AbstractEditor {
     if (this.props.lineNumbers != null) {
       gutters.push('CodeMirror-linenumbers', 'CodeMirror-foldgutter');
     }
-    if (isTextlintEnabled) {
-      gutters.push('CodeMirror-lint-markers');
-    }
 
     return (
       <div className={`grw-codemirror-editor ${styles['grw-codemirror-editor']}`}>
@@ -1119,7 +1091,6 @@ class CodeMirrorEditor extends AbstractEditor {
               'Shift-Tab': 'indentLess',
               'Ctrl-Q': (cm) => { cm.foldCode(cm.getCursor()) },
             },
-            lint,
           }}
           onCursor={this.cursorHandlerDebounced}
           onScroll={(editor, data) => {
@@ -1166,7 +1137,6 @@ class CodeMirrorEditor extends AbstractEditor {
 }
 
 CodeMirrorEditor.propTypes = Object.assign({
-  isTextlintEnabled: PropTypes.bool,
   lineNumbers: PropTypes.bool,
   editorSettings: PropTypes.object.isRequired,
   onMarkdownHelpButtonClicked: PropTypes.func,

+ 0 - 69
apps/app/src/components/PageEditor/DownloadDictModal.tsx

@@ -1,69 +0,0 @@
-import React, { useState } from 'react';
-
-import { useTranslation } from 'next-i18next';
-import {
-  Modal, ModalHeader, ModalBody, ModalFooter,
-} from 'reactstrap';
-
-type DownloadDictModalProps = {
-  isModalOpen: boolean
-  onEnableTextlint?: (isSkipAskingAgainChecked: boolean) => void;
-  onCancel?: () => void;
-};
-
-export const DownloadDictModal = (props: DownloadDictModalProps): JSX.Element => {
-  const { t } = useTranslation('');
-  const [isSkipAskingAgainChecked, setIsSkipAskingAgainChecked] = useState(false);
-
-  const onCancel = () => {
-    if (props.onCancel != null) {
-      props.onCancel();
-    }
-  };
-
-  const onConfirmEnableTextlint = () => {
-    if (props.onEnableTextlint != null) {
-      props.onEnableTextlint(isSkipAskingAgainChecked);
-    }
-  };
-
-  return (
-    <Modal isOpen={props.isModalOpen} toggle={onCancel} className="">
-      <ModalHeader tag="h4" toggle={onCancel} className="bg-warning">
-        <i className="icon-fw icon-question" />
-        Warning
-      </ModalHeader>
-      <ModalBody>
-        {t('modal_enable_textlint.confirm_download_dict_and_enable_textlint')}
-      </ModalBody>
-      <ModalFooter>
-        <div className="mr-3 custom-control custom-checkbox custom-checkbox-info">
-          <input
-            type="checkbox"
-            className="custom-control-input"
-            id="dont-ask-again"
-            checked={isSkipAskingAgainChecked}
-            onChange={e => setIsSkipAskingAgainChecked(e.target.checked)}
-          />
-          <label className="custom-control-label align-center" htmlFor="dont-ask-again">
-            {t('modal_enable_textlint.dont_ask_again')}
-          </label>
-        </div>
-        <button
-          type="button"
-          className="btn btn-outline-secondary"
-          onClick={onCancel}
-        >
-          {t('Cancel')}
-        </button>
-        <button
-          type="button"
-          className="btn btn-outline-primary ml-3"
-          onClick={onConfirmEnableTextlint}
-        >
-          {t('modal_enable_textlint.enable_textlint')}
-        </button>
-      </ModalFooter>
-    </Modal>
-  );
-};

+ 0 - 1
apps/app/src/components/PageEditor/Editor.tsx

@@ -32,7 +32,6 @@ export type EditorPropsType = {
   noCdn?: boolean,
   isUploadable?: boolean,
   isUploadableFile?: boolean,
-  isTextlintEnabled?: boolean,
   onChange?: (newValue: string, isClean?: boolean) => void,
   onUpload?: (file) => void,
   editorSettings?: IEditorSettings,

+ 3 - 74
apps/app/src/components/PageEditor/OptionsSelector.tsx

@@ -8,12 +8,10 @@ import {
 } from 'reactstrap';
 
 import { useIsIndentSizeForced } from '~/stores/context';
-import { useEditorSettings, useIsTextlintEnabled, useCurrentIndentSize } from '~/stores/editor';
+import { useEditorSettings, useCurrentIndentSize } from '~/stores/editor';
 
 import { DEFAULT_THEME, KeyMapMode } from '../../interfaces/editor-settings';
 
-import { DownloadDictModal } from './DownloadDictModal';
-
 
 const AVAILABLE_THEMES = [
   'eclipse', 'elegant', 'neo', 'mdn-like', 'material', 'dracula', 'monokai', 'twilight',
@@ -162,19 +160,13 @@ const IndentSizeSelector = memo(({ isIndentSizeForced, selectedIndentSize, onCha
 IndentSizeSelector.displayName = 'IndentSizeSelector';
 
 
-type ConfigurationDropdownProps = {
-  onConfirmEnableTextlint?: () => void,
-}
-
-const ConfigurationDropdown = memo(({ onConfirmEnableTextlint }: ConfigurationDropdownProps): JSX.Element => {
+const ConfigurationDropdown = memo((): JSX.Element => {
   const { t } = useTranslation();
 
   const [isCddMenuOpened, setCddMenuOpened] = useState(false);
 
   const { data: editorSettings, update } = useEditorSettings();
 
-  const { data: isTextlintEnabled, mutate: mutateTextlintEnabled } = useIsTextlintEnabled();
-
   const renderActiveLineMenuItem = useCallback(() => {
     if (editorSettings == null) {
       return <></>;
@@ -223,44 +215,6 @@ const ConfigurationDropdown = memo(({ onConfirmEnableTextlint }: ConfigurationDr
     );
   }, [editorSettings, t, update]);
 
-  const renderIsTextlintEnabledMenuItem = useCallback(() => {
-    if (editorSettings == null) {
-      return <></>;
-    }
-
-    const clickHandler = () => {
-      if (isTextlintEnabled) {
-        mutateTextlintEnabled(false);
-        return;
-      }
-
-      if (editorSettings.textlintSettings?.neverAskBeforeDownloadLargeFiles) {
-        mutateTextlintEnabled(true);
-        return;
-      }
-
-      if (onConfirmEnableTextlint != null) {
-        onConfirmEnableTextlint();
-      }
-    };
-
-    const iconClasses = ['text-info'];
-    if (isTextlintEnabled) {
-      iconClasses.push('ti ti-check');
-    }
-    const iconClassName = iconClasses.join(' ');
-
-    return (
-      <DropdownItem toggle={false} onClick={clickHandler}>
-        <div className="d-flex justify-content-between">
-          <span className="icon-container"></span>
-          <span className="menuitem-label">Textlint</span>
-          <span className="icon-container"><i className={iconClassName}></i></span>
-        </div>
-      </DropdownItem>
-    );
-  }, [editorSettings, isTextlintEnabled, mutateTextlintEnabled, onConfirmEnableTextlint]);
-
   return (
     <div className="my-0 form-group">
       <Dropdown
@@ -277,7 +231,6 @@ const ConfigurationDropdown = memo(({ onConfirmEnableTextlint }: ConfigurationDr
         <DropdownMenu>
           {renderActiveLineMenuItem()}
           {renderMarkdownTableAutoFormattingMenuItem()}
-          {renderIsTextlintEnabledMenuItem()}
           {/* <DropdownItem divider /> */}
         </DropdownMenu>
 
@@ -291,10 +244,7 @@ ConfigurationDropdown.displayName = 'ConfigurationDropdown';
 
 
 export const OptionsSelector = (): JSX.Element => {
-  const [isDownloadDictModalShown, setDownloadDictModalShown] = useState(false);
-
-  const { data: editorSettings, turnOffAskingBeforeDownloadLargeFiles } = useEditorSettings();
-  const { mutate: mutateTextlintEnabled } = useIsTextlintEnabled();
+  const { data: editorSettings } = useEditorSettings();
   const { data: isIndentSizeForced } = useIsIndentSizeForced();
   const { data: currentIndentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
 
@@ -318,28 +268,7 @@ export const OptionsSelector = (): JSX.Element => {
             onChange={newValue => mutateCurrentIndentSize(newValue)}
           />
         </span>
-        <span className="ml-2 ml-sm-4">
-          <ConfigurationDropdown
-            onConfirmEnableTextlint={() => setDownloadDictModalShown(true)}
-          />
-        </span>
       </div>
-
-      { editorSettings != null && !editorSettings.textlintSettings?.neverAskBeforeDownloadLargeFiles && (
-        <DownloadDictModal
-          isModalOpen={isDownloadDictModalShown}
-          onEnableTextlint={(isSkipAskingAgainChecked) => {
-            mutateTextlintEnabled(true);
-
-            if (isSkipAskingAgainChecked) {
-              turnOffAskingBeforeDownloadLargeFiles();
-            }
-
-            setDownloadDictModalShown(false);
-          }}
-          onCancel={() => setDownloadDictModalShown(false)}
-        />
-      )}
     </>
   );
 

+ 0 - 12
apps/app/src/interfaces/editor-settings.ts

@@ -1,14 +1,3 @@
-export interface ILintRule {
-  name: string;
-  options?: unknown;
-  isEnabled?: boolean;
-}
-
-export interface ITextlintSettings {
-  neverAskBeforeDownloadLargeFiles?: boolean;
-  textlintRules: ILintRule[];
-}
-
 export const DEFAULT_THEME = 'elegant';
 
 const KeyMapMode = {
@@ -25,7 +14,6 @@ export interface IEditorSettings {
   keymapMode: undefined | KeyMapMode,
   styleActiveLine: boolean,
   autoFormatMarkdownTable: boolean,
-  textlintSettings: undefined | ITextlintSettings;
 }
 
 export type EditorConfig = {

+ 1 - 11
apps/app/src/server/models/editor-settings.ts

@@ -2,7 +2,7 @@ import {
   Schema, Model, Document,
 } from 'mongoose';
 
-import { IEditorSettings, ITextlintSettings } from '~/interfaces/editor-settings';
+import { IEditorSettings } from '~/interfaces/editor-settings';
 
 import { getOrCreateModel } from '../util/mongoose-utils';
 
@@ -12,22 +12,12 @@ export interface EditorSettingsDocument extends IEditorSettings, Document {
 }
 export type EditorSettingsModel = Model<EditorSettingsDocument>
 
-const textlintSettingsSchema = new Schema<ITextlintSettings>({
-  neverAskBeforeDownloadLargeFiles: { type: Boolean, default: false },
-  textlintRules: {
-    type: [
-      { name: { type: String }, options: { type: Object }, isEnabled: { type: Boolean } },
-    ],
-  },
-});
-
 const editorSettingsSchema = new Schema<EditorSettingsDocument, EditorSettingsModel>({
   userId: { type: Schema.Types.ObjectId },
   theme: { type: String },
   keymapMode: { type: String },
   styleActiveLine: { type: Boolean, default: false },
   autoFormatMarkdownTable: { type: Boolean, default: true },
-  textlintSettings: textlintSettingsSchema,
 });
 
 

+ 0 - 14
apps/app/src/server/routes/apiv3/personal-setting.js

@@ -118,10 +118,6 @@ module.exports = (crowi) => {
       body('keymapMode').optional().isString(),
       body('styleActiveLine').optional().isBoolean(),
       body('autoFormatMarkdownTable').optional().isBoolean(),
-      body('textlintSettings.neverAskBeforeDownloadLargeFiles').optional().isBoolean(),
-      body('textlintSettings.textlintRules.*.name').optional().isString(),
-      body('textlintSettings.textlintRules.*.options').optional(),
-      body('textlintSettings.textlintRules.*.isEnabled').optional().isBoolean(),
     ],
     inAppNotificationSettings: [
       body('defaultSubscribeRules.*.name').isString(),
@@ -539,22 +535,12 @@ module.exports = (crowi) => {
 
     const {
       theme, keymapMode, styleActiveLine, autoFormatMarkdownTable,
-      textlintSettings,
     } = body;
 
     const document = {
       theme, keymapMode, styleActiveLine, autoFormatMarkdownTable,
     };
 
-    if (textlintSettings != null) {
-      if (textlintSettings.neverAskBeforeDownloadLargeFiles != null) {
-        Object.assign(document, { 'textlintSettings.neverAskBeforeDownloadLargeFiles': textlintSettings.neverAskBeforeDownloadLargeFiles });
-      }
-      if (textlintSettings.textlintRules != null) {
-        Object.assign(document, { 'textlintSettings.textlintRules': textlintSettings.textlintRules });
-      }
-    }
-
     // Insert if document does not exist, and return new values
     // See: https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
     const options = { upsert: true, new: true };

+ 0 - 17
apps/app/src/stores/editor.tsx

@@ -24,7 +24,6 @@ export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Er
 
 type EditorSettingsOperation = {
   update: (updateData: Partial<IEditorSettings>) => Promise<void>,
-  turnOffAskingBeforeDownloadLargeFiles: () => void,
 }
 
 // TODO: Enable localStorageMiddleware
@@ -56,25 +55,9 @@ export const useEditorSettings = (): SWRResponseWithUtils<EditorSettingsOperatio
       // invoke API
       await apiv3Put('/personal-setting/editor-settings', updateData);
     },
-    turnOffAskingBeforeDownloadLargeFiles: async() => {
-      const { data, mutate } = swrResult;
-
-      if (data == null) {
-        return;
-      }
-
-      // invoke API
-      await apiv3Put('/personal-setting/editor-settings', { textlintSettings: { neverAskBeforeDownloadLargeFiles: true } });
-      // revalidate
-      mutate();
-    },
   });
 };
 
-export const useIsTextlintEnabled = (): SWRResponse<boolean, Error> => {
-  return useStaticSWR<boolean, Error>('isTextlintEnabled', undefined, { fallbackData: false });
-};
-
 export const useCurrentIndentSize = (): SWRResponse<number, Error> => {
   const { data: defaultIndentSize } = useDefaultIndentSize();
   return useStaticSWR<number, Error>(

+ 0 - 2
apps/app/tsconfig.build.client.json

@@ -13,8 +13,6 @@
       "~/*": ["./src/*"],
       "^/*": ["./*"],
 
-      "@growi/codemirror-textlint": ["../../packages/codemirror-textlint/src"],
-
       "debug": ["./src/server/utils/logger/alias-for-debug"]
     }
   }

+ 0 - 2
apps/app/tsconfig.json

@@ -12,8 +12,6 @@
       "~/*": ["./src/*"],
       "^/*": ["./*"],
 
-      "@growi/codemirror-textlint": ["../../packages/codemirror-textlint/src"],
-
       "debug": ["./src/server/utils/logger/alias-for-debug"]
     }
   },