index.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import textlintRuleNoUnmatchedPair from '@textlint-rule/textlint-rule-no-unmatched-pair';
  2. import { TextlintKernel, TextlintKernelRule, TextlintRuleOptions } from '@textlint/kernel';
  3. import { AsyncLinter, Annotation } from 'codemirror/addon/lint/lint';
  4. import textlintToCodeMirror from 'textlint-message-to-codemirror';
  5. import textlintRuleCommonMisspellings from 'textlint-rule-common-misspellings';
  6. import textlintRuleDateWeekdayMismatch from 'textlint-rule-date-weekday-mismatch';
  7. // import textlintRuleEnCapitalization from 'textlint-rule-en-capitalization'; // omit because en-pos package is too big
  8. import textlintRuleJaHiraganaKeishikimeishi from 'textlint-rule-ja-hiragana-keishikimeishi';
  9. import textlintRuleJaNoAbusage from 'textlint-rule-ja-no-abusage';
  10. import textlintRuleJaNoInappropriateWords from 'textlint-rule-ja-no-inappropriate-words';
  11. import textlintRuleJaNoMixedPeriod from 'textlint-rule-ja-no-mixed-period';
  12. import textlintRuleJaNoRedundantExpression from 'textlint-rule-ja-no-redundant-expression';
  13. import textlintRuleJaUnnaturalAlphabet from 'textlint-rule-ja-unnatural-alphabet';
  14. import textlintRuleMaxComma from 'textlint-rule-max-comma';
  15. import textlintRuleMaxKanjiContinuousLen from 'textlint-rule-max-kanji-continuous-len';
  16. import textlintRuleMaxTen from 'textlint-rule-max-ten';
  17. import textlintRuleNoDoubleNegativeJa from 'textlint-rule-no-double-negative-ja';
  18. import textlintRuleNoDoubledConjunction from 'textlint-rule-no-doubled-conjunction';
  19. import textlintRuleNoDoubledJoshi from 'textlint-rule-no-doubled-joshi';
  20. import textlintRuleNoDroppingTheRa from 'textlint-rule-no-dropping-the-ra';
  21. import textlintRuleNoHankakuKana from 'textlint-rule-no-hankaku-kana';
  22. import textlintRuleNoKangxiRadicals from 'textlint-rule-no-kangxi-radicals';
  23. import textlintRuleNoMixedZenkakuAndHankakuAlphabet from 'textlint-rule-no-mixed-zenkaku-and-hankaku-alphabet';
  24. import textlintRuleNoNfd from 'textlint-rule-no-nfd';
  25. import textlintRuleNoSurrogatePair from 'textlint-rule-no-surrogate-pair';
  26. import textlintRuleNoZeroWidthSpaces from 'textlint-rule-no-zero-width-spaces';
  27. import textlintRulePeriodInListItem from 'textlint-rule-period-in-list-item';
  28. import textlintRulePreferTariTari from 'textlint-rule-prefer-tari-tari';
  29. import textlintRuleSentenceLength from 'textlint-rule-sentence-length';
  30. import textlintRuleUseSiUnits from 'textlint-rule-use-si-units';
  31. import { loggerFactory } from './utils/logger';
  32. type RulesConfigObj = {
  33. name: string,
  34. options?: unknown,
  35. isEnabled?: boolean,
  36. }
  37. type RuleExtension = {
  38. ext: string
  39. }
  40. const ruleModulesList = {
  41. 'no-unmatched-pair': textlintRuleNoUnmatchedPair,
  42. 'common-misspellings': textlintRuleCommonMisspellings,
  43. 'date-weekday-mismatch': textlintRuleDateWeekdayMismatch,
  44. // 'en-capitalization': textlintRuleEnCapitalization, // omit because en-pos package is too big
  45. 'ja-hiragana-keishikimeishi': textlintRuleJaHiraganaKeishikimeishi,
  46. 'ja-no-abusage': textlintRuleJaNoAbusage,
  47. 'ja-no-inappropriate-words': textlintRuleJaNoInappropriateWords,
  48. 'ja-no-mixed-period': textlintRuleJaNoMixedPeriod,
  49. 'ja-no-redundant-expression': textlintRuleJaNoRedundantExpression,
  50. 'ja-unnatural-alphabet': textlintRuleJaUnnaturalAlphabet,
  51. 'max-comma': textlintRuleMaxComma,
  52. 'max-kanji-continuous-len': textlintRuleMaxKanjiContinuousLen,
  53. 'max-ten': textlintRuleMaxTen,
  54. 'no-double-negative-ja': textlintRuleNoDoubleNegativeJa,
  55. 'no-doubled-conjunction': textlintRuleNoDoubledConjunction,
  56. 'no-doubled-joshi': textlintRuleNoDoubledJoshi,
  57. 'no-dropping-the-ra': textlintRuleNoDroppingTheRa,
  58. 'no-hankaku-kana': textlintRuleNoHankakuKana,
  59. 'no-kangxi-radicals': textlintRuleNoKangxiRadicals,
  60. 'no-mixed-zenkaku-and-hankaku-alphabet': textlintRuleNoMixedZenkakuAndHankakuAlphabet,
  61. 'no-nfd': textlintRuleNoNfd,
  62. 'no-surrogate-pair': textlintRuleNoSurrogatePair,
  63. 'no-zero-width-spaces': textlintRuleNoZeroWidthSpaces,
  64. 'period-in-list-item': textlintRulePeriodInListItem,
  65. 'prefer-tari-tari': textlintRulePreferTariTari,
  66. 'sentence-length': textlintRuleSentenceLength,
  67. 'use-si-units': textlintRuleUseSiUnits,
  68. };
  69. const logger = loggerFactory('growi:codemirror:codemirror-textlint');
  70. const kernel = new TextlintKernel();
  71. const textlintOption: TextlintRuleOptions<RuleExtension> = {
  72. ext: '.md',
  73. plugins: [
  74. {
  75. pluginId: 'markdown',
  76. plugin: require('textlint-plugin-markdown'),
  77. },
  78. ],
  79. };
  80. const createSetupRules = (rules, ruleOptions): TextlintKernelRule[] => (
  81. Object.keys(rules).map(ruleName => (
  82. {
  83. ruleId: ruleName,
  84. rule: rules[ruleName],
  85. options: ruleOptions[ruleName],
  86. }
  87. ))
  88. );
  89. export const createValidator = (rulesConfigArray: RulesConfigObj[] | null): AsyncLinter<RulesConfigObj[] | null> => {
  90. if (rulesConfigArray != null) {
  91. const filteredConfigArray = rulesConfigArray
  92. .filter((rule) => {
  93. if (ruleModulesList[rule.name] == null) {
  94. logger.error(`Textlint rule ${rule.name} is not installed`);
  95. }
  96. return (ruleModulesList[rule.name] != null && rule.isEnabled !== false);
  97. });
  98. const rules = filteredConfigArray
  99. .reduce((rules, rule) => {
  100. rules[rule.name] = ruleModulesList[rule.name];
  101. return rules;
  102. }, {});
  103. const rulesOption = filteredConfigArray
  104. .reduce((rules, rule) => {
  105. rules[rule.name] = rule.options || {};
  106. return rules;
  107. }, {});
  108. Object.assign(
  109. textlintOption,
  110. { rules: createSetupRules(rules, rulesOption) },
  111. );
  112. }
  113. const defaultSetupRules: TextlintKernelRule[] = Object.entries(ruleModulesList)
  114. .map(ruleName => ({
  115. ruleId: ruleName[0],
  116. rule: ruleName[1],
  117. }));
  118. if (rulesConfigArray == null) {
  119. Object.assign(
  120. textlintOption,
  121. { rules: defaultSetupRules },
  122. );
  123. }
  124. return (text, callback) => {
  125. if (!text) {
  126. callback([]);
  127. return;
  128. }
  129. kernel
  130. .lintText(text, textlintOption)
  131. .then((result) => {
  132. const lintMessages = result.messages;
  133. const lintErrors: Annotation[] = lintMessages.map(textlintToCodeMirror);
  134. callback(lintErrors);
  135. });
  136. };
  137. };