AnnLior commited on
Commit
0099dc2
·
verified ·
1 Parent(s): 958503c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +74 -5
index.html CHANGED
@@ -72,11 +72,79 @@
72
  </div>
73
 
74
  <script>
75
- // Публичный API LanguageTool.
76
- // Если тут будет CORS/блокировка — поменяйте на 'https://languagetool.org/api/v2/check'
77
  const API = 'https://api.languagetool.org/v2/check';
78
  const LIMIT = 20000;
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  const input = document.getElementById('input');
81
  const results = document.getElementById('results');
82
  const highlighted = document.getElementById('highlighted');
@@ -184,7 +252,7 @@ document.getElementById('btnSplit').onclick = () => {
184
  status.textContent = '';
185
  };
186
 
187
- /* ---------- Запрос к LanguageTool с подробными ошибками ---------- */
188
  async function checkChunk(text) {
189
  const body = new URLSearchParams({ text: text, language: 'ru-RU' });
190
  let res;
@@ -207,13 +275,14 @@ async function checkChunk(text) {
207
  throw new Error('HTTP ' + res.status + hint + (detail ? ' | ' + detail : ''));
208
  }
209
  const data = await res.json();
210
- return data.matches || [];
 
211
  }
212
 
213
  /* ---------- Проверка одного куска ---------- */
214
  async function runOne(idx) {
215
  const ch = chunks[idx];
216
- if (!ch || ch.done) return;
217
  status.textContent = `Проверяем кусок ${idx+1}…`;
218
  try {
219
  ch.matches = await checkChunk(ch.text);
 
72
  </div>
73
 
74
  <script>
 
 
75
  const API = 'https://api.languagetool.org/v2/check';
76
  const LIMIT = 20000;
77
 
78
+ /* ================== СТОП-ЛИСТ СЛОВ ================== */
79
+ // Слова, которые LanguageTool не должен проверять и предлагать замены.
80
+ // Регистр не важен. Можно с пробелами и дефисами.
81
+ const STOP_WORDS = [
82
+ 'Иезавель',
83
+ 'Иезавели',
84
+ 'Иезавелью',
85
+ // добавьте свои — каждое с новой строки в кавычках и с запятой
86
+ ];
87
+ const STOP_SET = new Set(STOP_WORDS.map(w => w.toLowerCase().trim()));
88
+
89
+ /* ================== ИГНОР-ЛИСТ ПРАВИЛ ================== */
90
+ // ID правил LanguageTool, которые нужно полностью игнорировать.
91
+ // Список ID можно смотреть на https://community.languagetool.org/rule/list?lang=ru
92
+ const IGNORED_RULES = new Set([
93
+ 'Many_PNN', // Загруженность предложения местоимениями
94
+ // добавьте сюда другие ID, если найдёте ненужные правила
95
+ ]);
96
+
97
+ /* ================== ФИЛЬТРЫ ================== */
98
+ function isInsideStopWord(text, offset, length) {
99
+ if (STOP_SET.size === 0) return false;
100
+ const target = text.substring(offset, offset + length).toLowerCase().trim();
101
+ if (STOP_SET.has(target)) return true;
102
+
103
+ // если LT выделил часть слова — проверим границы целого слова
104
+ const isLetter = c => /[а-яёa-z]/i.test(c);
105
+ const before = text[offset - 1] || ' ';
106
+ const after = text[offset + length] || ' ';
107
+ if (isLetter(before) || isLetter(after)) {
108
+ let s = offset, e = offset + length;
109
+ while (s > 0 && isLetter(text[s - 1])) s--;
110
+ while (e < text.length && isLetter(text[e])) e++;
111
+ const wholeWord = text.substring(s, e).toLowerCase().trim();
112
+ if (STOP_SET.has(wholeWord)) return true;
113
+ }
114
+ return false;
115
+ }
116
+
117
+ function isSillySuggestion(orig, sugg) {
118
+ if (!sugg) return false;
119
+ const o = orig.toLowerCase(), s = sugg.toLowerCase();
120
+ if (o === s) return false;
121
+ if (s.length > o.length * 2 || o.length > s.length * 2) return true;
122
+ const common = [...new Set(o)].filter(c => s.includes(c)).length;
123
+ const minLen = Math.min(o.length, s.length);
124
+ if (minLen > 3 && common < minLen / 2) return true;
125
+ return false;
126
+ }
127
+
128
+ function filterMatches(matches, text) {
129
+ return matches
130
+ .filter(m => !IGNORED_RULES.has(m.rule?.id))
131
+ .filter(m => !isInsideStopWord(text, m.offset, m.length))
132
+ .map(m => {
133
+ const orig = text.substring(m.offset, m.offset + m.length);
134
+ const good = m.replacements.filter(r => !isSillySuggestion(orig, r.value));
135
+ return { ...m, replacements: good };
136
+ })
137
+ .filter(m => {
138
+ // оставляем, если есть хоть одна замена
139
+ if (m.replacements.length > 0) return true;
140
+ // или если это орфографическая ошибка (её стоит показать даже без замен)
141
+ if (m.rule?.issueType === 'misspelling') return true;
142
+ // иначе — скрываем
143
+ return false;
144
+ });
145
+ }
146
+ /* ==================================================== */
147
+
148
  const input = document.getElementById('input');
149
  const results = document.getElementById('results');
150
  const highlighted = document.getElementById('highlighted');
 
252
  status.textContent = '';
253
  };
254
 
255
+ /* ---------- Запрос к LanguageTool ---------- */
256
  async function checkChunk(text) {
257
  const body = new URLSearchParams({ text: text, language: 'ru-RU' });
258
  let res;
 
275
  throw new Error('HTTP ' + res.status + hint + (detail ? ' | ' + detail : ''));
276
  }
277
  const data = await res.json();
278
+ // Пропускаем через стоп-лист, игнор правил и фильтр нелепых замен
279
+ return filterMatches(data.matches || [], text);
280
  }
281
 
282
  /* ---------- Проверка одного куска ---------- */
283
  async function runOne(idx) {
284
  const ch = chunks[idx];
285
+ if (!ch || ch.done) return false;
286
  status.textContent = `Проверяем кусок ${idx+1}…`;
287
  try {
288
  ch.matches = await checkChunk(ch.text);