Автор оригинала: FreeCodeCamp Community Member.
Я использовал приложение HEMingway, чтобы попытаться улучшить мои посты. В то же время я пытался найти идеи для небольших проектов. Я пришел с идеей интеграции редактора стилей HEMINGWAYW в редактор Markown. Поэтому мне нужно было узнать, как работал Хемингуэй!
Получение логики
Я понятия не имел, как приложение работало, когда я впервые начал. Он мог отправить текст на сервер, чтобы рассчитать сложность письма, но я ожидал, что он будет рассчитан на стороне клиента.
Открытие инструментов разработчиков в Chrome (Control + Shift + I или F12 в Windows/Linux, команда + опция + I на Mac) и навигация на Источники предоставил ответы Отказ Там я нашел файл, который я искал: hemingway3-web.js.
Этот код находится в доминированной форме, которая является болью читать и понимать. Чтобы решить это, я скопировал файл в VS-код и отформатировал документ ( Control + Shift + i for vs код). Это изменяет 3-строчный файл в файл 4859-линий со всем, что все отформатировано.
Исследуя код
Я начал смотреть через файл для всего, что я мог бы понять. Запуск файла содержится немедленно вызываемых функциональных выражений. У меня было мало представления о том, что происходило.
!function(e) {
function t(r) {
if (n[r])
return n[r].exports;
var o = n[r] = {
exports: {},
id: r,
loaded: !1
};
...Это продолжало около 200 строк, прежде чем я решил, что я, вероятно, читал код, чтобы заставить страницу пройти (реагировать?). Я начал снимать через остаток кода, пока я не нашел что-то, что я мог бы понять. (Я довольно много пропустил, что я бы позже нашел сквозь вызовы функций и смотрите на определение функции).
Первый бит кода, который я понял, был весь путь на линии 3496!
getTokens: function(e) {
var t = this.getAdverbs(e),
n = this.getQualifiers(e),
r = this.getPassiveVoices(e),
o = this.getComplexWords(e);
return [].concat(t, n, r, o).sort(function(e, t) {
return e.startIndex - t.startIndex
})
}И удивительно, все эти функции были определены прямо ниже. Теперь я знал, как приложение определило наречия, квалификаторы, пассивный голос и сложные слова. Некоторые из них очень просто. Приложение проверяет каждое слово против списков классификаторов, сложных слов и пассивных голосовых фраз. Это .getadverbs Фильтрует слова на основе того, заканчиваются ли они «LY», а затем проверяют, в списке нерешеных слов, заканчивающихся в «LY».
Следующий бит полезного кода был внедрение выделения слов или предложений. В этом коде есть строка:
e.highlight.hardSentences += h
«Хертик» было то, что я мог понять, что-то со смыслом. Затем я искал файл для Упорные препараты и получил 13 матчей. Это приводит к линии, которая рассчитала статистика читаемости:
n.stats.readability === i.default.readability.hard && (e.hardSentences += 1), n.stats.readability === i.default.readability.veryHard && (e.veryHardSentences += 1)
Теперь я знал, что был читабельность Параметр в обоих Статистика и I.default Отказ Поиск файла, я получил 40 матчей. Один из этих матчей был GetReadabilityStyle Функция, где они оценивают ваше письмо.
Есть три уровня: нормальные, жесткие и очень тяжелые.
t = e.words;
n = e.readingLevel;
return t < 14
? i.default.readability.normal
: n >= 10 && n < 14
? i.default.readability.hard
: n >= 14 ? i.default.readability.veryHard
: i.default.readability.normal;«Нормальный» – менее 14 слов, «жесткий» – это 10-14 слов, а «очень сложно» – более 14 слов.
Теперь, чтобы найти, как рассчитать уровень чтения.
Я провел некоторое время, пытаясь найти любое представление о том, как рассчитать уровень чтения. Я нашел его 4 строки над GetReadabilityStyle функция.
e = letters in paragraph;
t = words in paragraph;
n = sentences in paragraph;
getReadingLevel: function(e, t, n) {
if (0 === t
0 === n) return 0;
var r = Math.round(4.71 * (e / t) + 0.5 * (t / n) - 21.43);
return r <= 0 ? 0 : r;
}Это означает, что ваш счет составляет 4,71 * Среднее слово длина слова + 0,5 * Среднее длина предложения -21,43. Вот и все. Вот как классы Heamingway каждый из ваших предложений.
Другие интересные вещи, которые я нашел
- Комментарий Highlight (информация о вашем письме с правой стороны) является большим оператором коммутатора. Темные операторы используются для изменения ответа на основе того, насколько хорошо вы написали.
- Оценка идет до 16, прежде чем он классифицируется как «аспирантура».
Что я собираюсь сделать с этим
Я планирую сделать базовый веб-сайт и применить то, что я узнал из-за деконструирования приложения Hemingway. Ничто не нравится, больше как упражнение для реализации какой-то логики. Раньше я создал предварительный просмотр Markdown, поэтому я также мог попытаться создать приложение записи с помощью системы выделения и оценки.
Выяснив, как работает приложение Hemingway, я решил реализовать то, что я научился сделать много упрощенной версии.
Я хотел убедиться, что я сохранял его базовым, сосредоточившись на логике больше, что укладка. Я решил пойти с простой входной коробкой текстового поля.
Вызовы
1. Как обеспечить производительность. Спасание весь документ на каждой ключевой прессу может быть очень вычислительно дорогим. Это может привести к блокировке UX, которое, очевидно, не то, что мы хотим.
2. Как разделить текст в пункты, предложения и слова для выделения.
Возможные решения
- Только сканирование абзацев, которые меняются. Сделайте это, подсчитав количество абзацев и сравниваем это до документа до изменения. Используйте это, чтобы найти абзац, который изменился или новый абзац и только сканирует, что один.
- Есть кнопка для сканирования документа. Это массивно уменьшает вызовы функции сканирования.
2. Используйте то, что я узнал из Хемингуэя – каждый абзац – это
и любые предложения или слова, которые нуждаются в выделении, обернуты во внутреннем с нужным классом.
Создание приложения
Недавно я прочитал много статей о создании минимального жизнеспособного продукта (MVP), поэтому я решил, что я бы запустил этот маленький проект одинаково. Это означало, чтобы все было просто. Я решил пойти с коробкой ввода, кнопку для сканирования и вывода.
Это было очень легко настроить в моем файле index.html.
Fake Hemingway Fake Hemingway
Теперь начать на интересной части. Теперь, чтобы получить работу JavaScript.
Первое, что нужно сделать, было сделать текст из текстового поля в выходную область. Это включает в себя поиск входного текста и установку внутреннего HTML вывода к этому тексту.
function format() {
let inputArea = document.getElementById("text-area");
let text = inputArea.value;
let outputArea = document.getElementById("output");
outputArea.innerHTML = text;
}Далее является получение текста разделения в пункты. Это достигается путем разделения текста «\ N» и поместив каждый из них в тег
. Для этого мы можем сопоставить на массив абзацев, вкладывая их между тегами
. Использование шаблонов строки делает это очень легко.
let paragraphs = text.split("\n");
let inParagraphs = paragraphs.map(paragraph => `${paragraph}
`);
outputArea.innerHTML = inParagraphs.join(" ");Хотя я работал, хотя я стал раздраженным копированием и вставлять текст теста в текстовое поле. Чтобы решить это, я реализовал немедленно вызываемое выражение функции (IIFE), чтобы заполнить текстовое поле, когда веб-страница отображается.
(function start() {
let inputArea = document.getElementById("text-area");
let text = `The app highlights lengthy, …. compose something new.`;
inputArea.value = text;
})();Теперь текстовое поле было предварительно заполнено текстом теста всякий раз, когда вы загружаете или обновите веб-страницу. Намного проще.
Подсветка
Теперь, когда я хорошо оказал текст, и я тестировал на последовательный текст, мне пришлось работать над подсветкой. Первый тип выделения я решил справиться, было твердое и очень тяжелое предложение.
Первый этап этого является петля по каждому абзацу и разделить их в массив предложений. Я сделал это, используя функцию «разделения ()», разделение на все полную остановку с пространством после него.
let sentences = paragraph.split('. ');Из Хеминвей я знал, что мне нужно было рассчитать количество слов и уровень каждого из предложений. Уровень предложения зависит от средней длины слов и средних слов на предложение. Вот как я рассчитал количество слов и общих слов на предложение.
let words = sentence.split(" ").length;
let letters = sentence.split(" ").join("").length;Используя эти цифры, я мог бы использовать уравнение, которое я нашел в приложении HEMingway.
let level = Math.round(4.71 * (letters / words) + 0.5 * words / sentences — 21.43);
С уровнем и количеством слов для каждого из предложений, установите уровень сложности.
if (words < 14) {
return sentence;
} else if (level >= 10 && level < 14) {
return `${sentence}`;
} else if (level >= 14) {
return `${sentence}`;
} else {
return sentence;
}Этот код говорит, что если предложение длиннее 14 слов, и имеет уровень от 10 до 14, то его сложно, если дольше 14 слов и имеет уровень 14 или вверх, то это очень сильно. Я снова использовал шаблонные строки, но включите класс в тегах охвата. Вот как я собираюсь определить подсветку.
Файл CSS действительно прост; Он просто имеет каждый из классов (наречие, пассив, привлечение) и устанавливает свой цвет фона. Я взял точные цвета из приложения Hemingway.
Как только предложения были возвращены, я присоединяюсь к ним все вместе, чтобы сделать каждый из абзацев.
На данный момент я понял, что в моем коде возникли несколько проблем.
- Там не было полных остановок. Когда я разделяю абзацы в предложения, я удалил все полные остановки.
- Числа букв в предложении включали запятые, тире, колоны и полуобытия.
Мое первое решение было очень примитивным, но оно сработало. Я использовал разделенный («символ») и присоединиться («), чтобы удалить пунктуацию, а затем добавить». на конец. Whist это сработало, я искал лучшее решение. Хотя у меня нет большого опыта, используя Regex, я знал, что это будет лучшее решение. После некоторого гугула я нашел гораздо более элегантное решение.
let cleanSentence = sent.replace(/[^a-z0–9. ]/gi, "") + ".";
С этим сделано, у меня был частично рабочий продукт.
Следующее, что я решил справиться, это наречие. Чтобы найти наречие, HEMingway просто находит слова, которые заканчиваются в «LY», а затем проверяют, что он не в списке слов нереплеба «Ly». Было бы плохо, если «применить» или «Италию» были помечены как наречие.
Чтобы найти эти слова, я взял предложения и разделил их в массив слов. Я сопоставлен через этот массив и использовал его заявление.
if(word.match(/ly$/) &&, !lyWords[word] ){
return `${word}`;
} else {
return word
};Whist это сработало большую часть времени, я нашел несколько исключений. Если последовало слово знаком пунктуации, то он не совпал заканчиваться «LY». Например, «крокодил элегантно скользил; это добыча, не знающая», будет иметь слово «элегантно»; в массиве. Решить это, я повторно использовал .replace (/^ a-z0-9.]/Gi, "") Функциональность для очистки каждого из слов.
Еще одним исключением было, если бы слово было капитализировано, которое было легко решено, позвонив Толкание () на строке.
Теперь у меня был результат, который работал с наречиями и подчеркивая отдельных слов. Затем я реализовал очень похожий метод для сложных и квалификационных слов. Это было, когда я понял, что больше не был просто ищет отдельных слов, я искал фразы. Я должен был изменить свой подход от проверки, был ли каждое слово в списке, чтобы увидеть, если предложение содержит каждую из фраз.
Для этого я использовал .indexof () функция на предложениях. Если был индекс слова или фразы, я вставил метку промежутка открытия в этом индексе, а затем тег закрытия после длины ключа.
let qualifiers = getQualifyingWords();
let wordList = Object.keys(qualifiers);
wordList.forEach(key => {
let index = sentence.toLowerCase().indexOf(key);
if (index >= 0) {
sentence =
sentence.slice(0, index) +
'' +
sentence.slice(index, index + key.length) +
"" +
sentence.slice(index + key.length);
}
});С этой работой он начинает все больше выглядеть как редактор помингинга.
Последний кусок выделенной головоломки для реализации был пассивный голос. Хемингуэй использовал функцию 30 линий, чтобы найти все пассивные фразы. Я решил использовать большую часть логики, который реализован HEMINGWAY, но заказывает процесс по-разному. Они выглядели, чтобы найти любые слова, которые были в списке (есть, были, были, были, были, были, быть), а затем проверили, закончилось ли следующее слово «ed».
Я зацикливаю каждый из слов в предложении и проверил, если они закончились в «Эд». Для каждого слова «ЭД» я нашел, я проверил, было ли предыдущее слово в списке предварительных слов. Это казалось намного проще, но может быть менее исполнительным.
С этой работой у меня было приложение, которое подчеркивало все, что я хотел. Это мой MVP.
Тогда я ударил проблему
Как я писал этот пост, я понял, что в моем коде из моих огромных ошибок были две огромные ошибки.
// from getQualifier and getComplex let index = sentence.toLowerCase().indexOf(key); // from getPassive let index = words.indexOf(match);
Они когда-либо найдут только первый экземпляр ключа или совпадения. Вот пример результатов, которые этот код будет производить.
«Возможно» и «были отмечены» должны были быть выделены дважды каждый, но они не.
Чтобы исправить ошибку в GetQualifier и GetComplex, я решил использовать рекурсию. Я создал indandandspan Функция, которая использует. indexof () Чтобы найти первый случай слова или фразы. Он разбивает предложение на 3 части: перед фразой фраза, после фразы. Рекурсион работает, передавая строку «после фразы» обратно в функцию. Это будет продолжаться до тех пор, пока больше нет экземпляров фразы, где строка будет просто передаваться обратно.
function findAndSpan(sentence, string, type) {
let index = sentence.toLowerCase().indexOf(key);
if (index >= 0) {
sentence =
sentence.slice(0, index) +
`` +
sentence.slice(index, index + key.length) +
"" +
findAndSpan(
sentence.slice(index + key.length),
key,
type);
}
return sentence;
}Что-то очень похожее нужно было сделать для пассивного голоса. Рекурсия была практически идентичной структурой, передавая остальные элементы массива вместо левой строки. Результат рекурсионного вызова был распространен в массив, который затем вернулся. Теперь приложение может иметь дело с повторными наречиями, квалификаторами, сложными фразами и пассивным голосом.
Счетчик статистики
Последнее, что я хотел работать, была хорошая линия коробок, информирующая вас о том, сколько наречия или сложных слов, которые вы использовали.
Чтобы сохранить данные, которые я создал объект с ключами для каждого из параметров, которые я хотел рассчитать. Я начал, имея эту переменную в качестве глобальной переменной, но знал, что мне придется изменить это позже.
Теперь мне пришлось заполнить ценности. Это было сделано путем увеличения ценности каждый раз, когда он был найден.
data.sentences += sentence.length or data.adverbs += 1
Значения, необходимые для сброса каждый раз, когда сканирование было запущено, чтобы убедиться, что значения не увеличиваются.
С нужными значениями я должен был получить их рендеринг на экране. Я изменил структуру HTML-файла, чтобы входную коробку и выходную область находились в Div слева, оставив правый Div для счетчиков. Эти счетчики пустые Div с соответствующим идентификатором и классом, а также класс «счетчика».
С помощью этих Divs я использовал Document.Queryselector, чтобы установить внутренний HTML для каждого из счетчиков с использованием собранных данных. С небольшим количеством стайлинга класса «Counter» веб-приложение было завершено. Попробуйте здесь Или посмотри на Мой код здесь.