乞力马扎罗山 海明威_我如何对海明威编辑器(一种流行的写作应用程序)进行反向工程,并从泰国的海滩上构建了自己的数据库
乞力馬扎羅山 海明威
I’ve been using the Hemingway App to try to improve my posts. At the same time I’ve been trying to find ideas for small projects. I came up with the idea of integrating a Hemingway style editor into a markdown editor. So I needed to find out how Hemingway worked!
我一直在使用海明威應(yīng)用程序來嘗試改善我的帖子。 同時(shí),我一直在努力尋找小型項(xiàng)目的想法。 我想到了將海明威樣式編輯器集成到markdown編輯器中的想法。 因此,我需要了解海明威的運(yùn)作方式!
掌握邏輯 (Getting the Logic)
I had no idea how the app worked when I first started. It could have sent the text to a server to calculate the complexity of the writing, but I expected it to be calculated client side.
我不知道我第一次啟動(dòng)時(shí)該應(yīng)用程序是如何工作的。 它可以將文本發(fā)送到服務(wù)器以計(jì)算編寫的復(fù)雜程度,但我希望它可以在客戶端進(jìn)行計(jì)算。
Opening developer tools in Chrome ( Control + Shift + I or F12 on Windows/Linux, Command + Option + I on Mac) and navigating to Sources provided the answers. There, I found the file I was looking for: hemingway3-web.js.
在Chrome中打開開發(fā)人員工具(在Windows / Linux上為Control + Shift + I或F12,在Mac上為Command + Option + I),然后導(dǎo)航至Sources提供了答案。 在那里,我找到了要查找的文件: hemingway3-web.js。
This code is in a minified form, which is a pain to read and understand. To solve this, I copied the file into VS Code and formatted the document (Control+ Shift + I for VS Code). This changes a 3-line file into a 4859-line file with everything formatted nicely.
該代碼采用最小化形式,難以閱讀和理解。 為了解決這個(gè)問題,我將文件復(fù)制到VS Code并格式化了文檔(VS Code為Control + Shift + I )。 這會(huì)將3行文件更改為4859行文件,所有文件的格式都很好。
探索代碼 (Exploring the Code)
I started to look through the file for anything that I could make sense of. The start of the file contained immediately invoked function expressions. I had little idea of what was happening.
我開始瀏覽文件,以查找所有我可能理解的東西。 文件的開頭包含立即調(diào)用的函數(shù)表達(dá)式。 我對(duì)發(fā)生的事情一無所知。
!function(e) {function t(r) {if (n[r])return n[r].exports;var o = n[r] = {exports: {},id: r,loaded: !1}; ...This continued for about 200 lines before I decided that I was probably reading the code to make the page run (React?). I started skimming through the rest of the code until I found something I could understand. (I missed quite a lot that I would later find through finding function calls and looking at the function definition).
這持續(xù)了大約200行,然后我決定我可能正在閱讀使頁面運(yùn)行的代碼(對(duì)嗎?)。 我開始瀏覽其余的代碼,直到發(fā)現(xiàn)我可以理解的內(nèi)容。 (我錯(cuò)過了很多,以后會(huì)通過查找函數(shù)調(diào)用并查看函數(shù)定義來發(fā)現(xiàn))。
The first bit of code I understood was all the way at line 3496!
我理解的第一部分代碼一直在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}) }And amazingly, all these functions were defined right below. Now I knew how the app defined adverbs, qualifiers, passive voice, and complex words. Some of them are very simple. The app checks each word against lists of qualifiers, complex words, and passive voice phrases. this.getAdverbs filters words based on whether they end in ‘ly’ and then checks whether it’s in the list of non-adverb words ending in ‘ly’.
令人驚訝的是,所有這些功能都在下面定義。 現(xiàn)在,我知道了該應(yīng)用程序如何定義副詞,限定詞,被動(dòng)語態(tài)和復(fù)雜的單詞。 其中一些非常簡(jiǎn)單。 該應(yīng)用程序根據(jù)限定詞,復(fù)雜詞和被動(dòng)語音短語列表檢查每個(gè)詞。 this.getAdverbs根據(jù)是否以'ly'結(jié)尾的單詞進(jìn)行過濾,然后檢查其是否在以'ly'結(jié)尾的非副詞列表中。
The next bit of useful code was the implementation of highlighting words or sentences. In this code there is a line:
下一個(gè)有用的代碼是突出顯示單詞或句子的實(shí)現(xiàn)。 這段代碼中有一行:
e.highlight.hardSentences += h‘hardSentences’ was something I could understand, something with meaning. I then searched the file for hardSentences and got 13 matches. This lead to a line that calculated the readability stats:
“ hardSentences”是我能理解的,有意義的東西。 然后,我在文件中搜索hardSentences并獲得了13個(gè)匹配項(xiàng)。 這導(dǎo)致一行計(jì)算了可讀性統(tǒng)計(jì)信息:
n.stats.readability === i.default.readability.hard && (e.hardSentences += 1), n.stats.readability === i.default.readability.veryHard && (e.veryHardSentences += 1)Now I knew that there was a readability parameter in both stats and i.default. Searching the file, I got 40 matches. One of those matches was a getReadabilityStyle function, where they grade your writing.
現(xiàn)在我知道在stats和i.default中都有一個(gè)readability參數(shù)。 搜索文件,我找到40個(gè)匹配項(xiàng)。 其中一項(xiàng)匹配項(xiàng)是getReadabilityStyle函數(shù),可在其中對(duì)您的寫作進(jìn)行評(píng)分。
There are three levels: normal, hard and very hard.
分為三個(gè)級(jí)別:正常,困難和非常困難。
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;“Normal” is less than 14 words, “hard” is 10–14 words, and “very hard” is more than 14 words.
“正常”少于14個(gè)單詞,“困難”為10-14個(gè)單詞,“非常困難”大于14個(gè)單詞。
Now to find how to calculate the reading level.
現(xiàn)在找到如何計(jì)算閱讀水平。
I spent a while here trying to find any notion of how to calculate the reading level. I found it 4 lines above the getReadabilityStyle function.
我在這里花了一段時(shí)間試圖找到關(guān)于如何計(jì)算閱讀水平的任何概念。 我在getReadabilityStyle函數(shù)上方找到4行。
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; }That means your score is 4.71 * average word length + 0.5 * average sentence length -21.43. That’s it. That is how Hemingway grades each of your sentences.
這意味著您的分?jǐn)?shù)是4.71 *平均單詞長(zhǎng)度+ 0.5 *平均句子長(zhǎng)度-21.43。 而已。 這就是海明威為您的每個(gè)句子評(píng)分的方式。
我發(fā)現(xiàn)的其他有趣的東西 (Other Interesting Things I Found)
- The highlight commentary (information about your writing on the right hand side) is a big switch statement. Ternary statements are used to change the response based on how well you’ve written. 最重要的評(píng)論(關(guān)于您的寫作的信息在右側(cè))是一個(gè)重要的聲明。 三元語句用于根據(jù)您的寫作水平來更改響應(yīng)。
- The grading goes up to 16 before it’s classed as “Post-Graduate” level. 在被歸類為“研究生”級(jí)別之前,該評(píng)分最高可達(dá)16。
我要怎么辦 (What I’m going to do with this)
I am planning to make a basic website and apply what I’ve learned from deconstructing the Hemingway app. Nothing fancy, more as an exercise for implementing some logic. I’ve built a Markdown previewer before, so I might also try to create a writing application with the highlighting and scoring system.
我打算建立一個(gè)基本的網(wǎng)站,并運(yùn)用我從解構(gòu)海明威應(yīng)用程序中學(xué)到的知識(shí)。 沒什么,更像是實(shí)施一些邏輯的練習(xí)。 我之前已經(jīng)構(gòu)建了Markdown預(yù)覽器,所以我也可以嘗試使用突出顯示和評(píng)分系統(tǒng)創(chuàng)建一個(gè)書寫應(yīng)用程序。
創(chuàng)建我自己的海明威應(yīng)用程序 (Creating My Own Hemingway App)
Having figured out how the Hemingway app works, I then decided to implement what I had learnt to make a much simplified version.
在弄清楚了海明威應(yīng)用程序的工作原理之后,我決定實(shí)施我學(xué)到的東西來制作一個(gè)簡(jiǎn)化得多的版本。
I wanted to make sure that I was keeping it basic, focusing on the logic more that the styling. I chose to go with a simple text box entry box.
我想確保自己保持基本狀態(tài),而不是僅關(guān)注樣式邏輯。 我選擇了一個(gè)簡(jiǎn)單的文本框輸入框。
挑戰(zhàn)性 (Challenges)
1. How to assure performance. Rescanning the whole document on every key press could be very computationally expensive. This could result in UX blocking which is obviously not what we want.
1.如何確保性能。 在每次按鍵時(shí)重新掃描整個(gè)文檔可能在計(jì)算上非常昂貴。 這可能會(huì)導(dǎo)致UX阻止,這顯然不是我們想要的。
2. How to split up the text into paragraphs, sentences and words for highlighting.
2.如何將文本分為段落,句子和單詞以突出顯示。
可能的解決方案 (Possible Solutions)
- Only rescan the paragraphs that change. Do this by counting the number of paragraphs and comparing that to the document before the change. Use this to find the paragraph that has changed or the new paragraph and only scan that one. 僅重新掃描更改的段落。 通過計(jì)算段落數(shù)并將其與更改前的文檔進(jìn)行比較來做到這一點(diǎn)。 使用它來查找已更改的段落或新段落,然后僅掃描該段落。
- Have a button to scan the document. This massively reduces the calls of the scanning function. 有一個(gè)按鈕來掃描文檔。 這大大減少了掃描功能的調(diào)用。
2. Use what I learnt from Hemingway?—?every paragraph is a <p> and any sentences or words that need highlighting are wrapped in an internal <span> with the necessary class.
2.使用我從海明威中學(xué)到的知識(shí)-每個(gè)段落都是一個(gè)<p>,任何需要突出顯示的句子或單詞都包裝在帶有必需類的內(nèi)部<span>中。
構(gòu)建應(yīng)用 (Building the App)
Recently I’ve read a lot of articles about building a Minimum Viable Product (MVP) so I decided that I would run this little project the same. This meant keeping everything simple. I decided to go with an input box, a button to scan and an output area.
最近,我讀了很多有關(guān)構(gòu)建最低限度可行產(chǎn)品(MVP)的文章,因此我決定我將以同樣的方式運(yùn)行這個(gè)小項(xiàng)目。 這意味著保持一切簡(jiǎn)單。 我決定帶一個(gè)輸入框,一個(gè)要掃描的按鈕和一個(gè)輸出區(qū)域。
This was all very easy to set up in my index.html file.
在我的index.html文件中設(shè)置所有這些都很容易。
<link rel=”stylesheet” href=”index.css”> <title>Fake Hemingway</title> <div><h1>Fake Hemingway</h1><textarea name=”” id=”text-area” rows=”10"></textarea><button onclick=”format()”>Test Me</button><div id=”output”></div> </div> <script src=”index.js”></script>Now to start on the interesting part. Now to get the Javascript working.
現(xiàn)在開始有趣的部分。 現(xiàn)在開始運(yùn)行Javascript。
The first thing to do was to render the text from the text box into the output area. This involves finding the input text and setting the output’s inner html to that text.
首先要做的是將文本從文本框中渲染到輸出區(qū)域中。 這涉及查找輸入文本并將輸出的內(nèi)部html設(shè)置為該文本。
function format() {let inputArea = document.getElementById(“text-area”);let text = inputArea.value;let outputArea = document.getElementById(“output”);outputArea.innerHTML = text; }Next is getting the text split into paragraphs. This is accomplished by splitting the text by ‘\n’ and putting each of these into a <p> tag. To do this we can map over the array of paragraphs, putting them in between <p> tags. Using template strings makes doing this very easy.
接下來是將文本分成幾段。 這可以通過用'\ n'分割文本并將每個(gè)文本放入<p>標(biāo)記中來實(shí)現(xiàn)。 為此,我們可以映射段落數(shù)組,將其放在<p>標(biāo)記之間。 使用模板字符串使此操作非常容易。
let paragraphs = text.split(“\n”); let inParagraphs = paragraphs.map(paragraph => `<p>${paragraph}</p>`); outputArea.innerHTML = inParagraphs.join(“ “);Whilst I was working though that, I was becoming annoyed having to copy and paste the test text into the text box. To solve this, I implemented an Immediately Invoked Function Expression (IIFE) to populate the text box when the web page renders.
雖然我當(dāng)時(shí)正在工作,但是我不得不將測(cè)試文本復(fù)制并粘貼到文本框中感到非常惱火。 為了解決這個(gè)問題,我實(shí)現(xiàn)了立即調(diào)用函數(shù)表達(dá)式(IIFE),以便在渲染網(wǎng)頁時(shí)填充文本框。
(function start() {let inputArea = document.getElementById(“text-area”);let text = `The app highlights lengthy, …. compose something new.`;inputArea.value = text; })();Now the text box was pre-populated with the test text whenever you load or refresh the web page. Much simpler.
現(xiàn)在,無論何時(shí)加載或刷新網(wǎng)頁,文本框都會(huì)預(yù)填充測(cè)試文本。 簡(jiǎn)單得多。
突出顯示 (Highlighting)
Now that I was rendering the text well and I was testing on a consistent text, I had to work on the highlighting. The first type of highlighting I decided to tackle was the hard and very hard sentence highlighting.
既然我已經(jīng)很好地渲染了文本,并且正在對(duì)一致的文本進(jìn)行測(cè)試,那么我必須進(jìn)行突出顯示。 我決定要解決的第一種突出顯示方式是句子的突出顯示。
The first stage of this is to loop over every paragraph and split them into an array of sentences. I did this using a `split()` function, splitting on every full stop with a space after it.
第一步是遍歷每個(gè)段落并將它們分成句子數(shù)組。 我使用一個(gè)`split()`函數(shù)來做到這一點(diǎn),在每個(gè)句號(hào)處都用空格分隔。
let sentences = paragraph.split(‘. ’);From Heminway I knew that I needed to calculate the number of words and level of each of the sentences. The level of the sentence is dependant on the average length of words and the average words per sentence. Here is how I calculated the number of words and the total words per sentence.
從海明威,我知道我需要計(jì)算單詞的數(shù)量和每個(gè)句子的級(jí)別。 句子的級(jí)別取決于單詞的平均長(zhǎng)度和每個(gè)句子的平均單詞。 這是我計(jì)算每個(gè)句子的單詞數(shù)和總單詞數(shù)的方法。
let words = sentence.split(“ “).length; let letters = sentence.split(“ “).join(“”).length;Using these numbers, I could use the equation that I found in the Hemingway app.
使用這些數(shù)字,我可以使用在海明威應(yīng)用程序中找到的方程式。
let level = Math.round(4.71 * (letters / words) + 0.5 * words / sentences — 21.43);With the level and number of words for each of the sentences, set their difficulty level.
使用每個(gè)句子的單詞級(jí)別和數(shù)量,設(shè)置其難度級(jí)別。
if (words < 14) {return sentence; } else if (level >= 10 && level < 14) {return `<span class=”hardSentence”>${sentence}</span>`; } else if (level >= 14) {return `<span class=”veryHardSentence”>${sentence}</span>`; } else {return sentence; }This code says that if a sentence is longer than 14 words and has a level of 10 to 14 then its hard, if its longer than 14 words and has a level of 14 or up then its very hard. I used template strings again but include a class in the span tags. This is how I’m going to define the highlighting.
該代碼表示??,如果句子長(zhǎng)于14個(gè)單詞且級(jí)別為10到14,則很難;如果句子長(zhǎng)于14個(gè)單詞且級(jí)別為14或更高,則它很難。 我再次使用了模板字符串,但在span標(biāo)簽中包含了一個(gè)類。 這就是我要定義突出顯示的方式。
The CSS file is really simple; it just has each of the classes (adverb, passive, hardSentence) and sets their background colour. I took the exact colours from the Hemingway app.
CSS文件非常簡(jiǎn)單。 它僅具有每個(gè)類(副詞,被動(dòng),hardSentence)并設(shè)置其背景色。 我從海明威應(yīng)用程序中提取了確切的顏色。
Once the sentences have been returned, I join them all together to make each of the paragraphs.
句子返回后,我將它們?nèi)亢喜⒃谝黄鹨詷?gòu)成每個(gè)段落。
At this point, I realised that there were a few problems in my code.
至此,我意識(shí)到我的代碼中存在一些問題。
- There were no full stops. When I split the paragraphs into sentences, I had removed all of the full stops. 沒有句號(hào)。 當(dāng)我將段落分成句子時(shí),我刪除了所有句號(hào)。
- The numbers of letters in the sentence included the commas, dashes, colons and semi-colons. 句子中字母的數(shù)量包括逗號(hào),破折號(hào),冒號(hào)和分號(hào)。
My first solution was very primitive but it worked. I used split(‘symbol’) and join(‘’) to remove the punctuation and then appended ‘.’ onto the end. Whist it worked, I searched for a better solution. Although I don’t have much experience using regex, I knew that it would be the best solution. After some Googling I found a much more elegant solution.
我的第一個(gè)解決方案非常原始,但是有效。 我使用split('symbol')和join('')刪除標(biāo)點(diǎn)符號(hào),然后附加了'。'。 到最后。 一直奏效,我一直在尋找更好的解決方案。 盡管我沒有太多使用正則表達(dá)式的經(jīng)驗(yàn),但我知道這將是最好的解決方案。 經(jīng)過一番谷歌搜索后,我發(fā)現(xiàn)了一個(gè)更為優(yōu)雅的解決方案。
let cleanSentence = sent.replace(/[^a-z0–9. ]/gi, “”) + “.”;With this done, I had a partially working product.
完成此操作后,我得到了部分工作的產(chǎn)品。
The next thing I decided to tackle was the adverbs. To find an adverb, Hemingway just finds words that end in ‘ly’ and then checks that it isn’t on a list of non-adverb ‘ly’ words. It would be bad if ‘a(chǎn)pply’ or ‘Italy’ were tagged as adverbs.
我決定解決的下一件事是副詞。 為了找到副詞,海明威只是找到以“ ly”結(jié)尾的單詞,然后檢查它是否不在非副詞“ ly”單詞列表中。 如果將'apply'或'Italy'標(biāo)記為副詞,那將是不好的。
To find these words, I took the sentences and split them into an arary of words. I mapped over this array and used an IF statement.
為了找到這些單詞,我采用了句子并將其拆分為單詞集。 我在此數(shù)組上映射并使用了IF語句。
if(word.match(/ly$/) &&, !lyWords[word] ){return `<span class=”adverb”>${word}</span>`; } else {return word };Whist this worked most of the time, I found a few exceptions. If a word was followed by a punctuation mark then it didn’t match ending with ‘ly’. For example, “The crocodile glided elegantly; it’s prey unaware” would have the word ‘elegantly;’ in the array. To solve this I reused the .replace(/^a-z0-9. ]/gi,””) functionality to clean each of the words.
在大多數(shù)情況下,這都是可行的,我發(fā)現(xiàn)了一些例外。 如果單詞后面帶有標(biāo)點(diǎn)符號(hào),則該單詞與“ ly”結(jié)尾不匹配。 例如,“鱷魚優(yōu)雅滑翔; 獵物沒有意識(shí)到”會(huì)帶有“優(yōu)雅”一詞; 在數(shù)組中。 為了解決這個(gè)問題,我重用了.replace(/^a-z0-9. ]/gi,””)功能來清理每個(gè)單詞。
Another exception was if the word was capitalised, which was easily solved by calling toLowerCase()on the string.
另一個(gè)例外是單詞大寫,可以通過在字符串上調(diào)用toLowerCase()輕松解決。
Now I had a result that worked with adverbs and highlighting individual words. I then implemented a very similar method for complex and qualifying words. That was when I realised that I was no longer just looking for individual words, I was looking for phrases. I had to change my approach from checking if each word was in the list to seeing if the sentence contained each of the phrases.
現(xiàn)在,我得到了處理副詞并突出顯示單個(gè)單詞的結(jié)果。 然后,我對(duì)復(fù)雜且合格的單詞實(shí)施了一種非常相似的方法。 從那時(shí)起,我意識(shí)到我不再只是在尋找單個(gè)單詞,而是在尋找短語。 我不得不將方法從檢查每個(gè)單詞是否在列表中更改為查看句子是否包含每個(gè)短語。
To do this I used the .indexOf() function on the sentences. If there was an index of the word or phrase, I inserted an opening span tag at that index and then the closing span tag after the key length.
為此,我在句子上使用了.indexOf()函數(shù)。 如果有單詞或短語的索引,我會(huì)在該索引處插入一個(gè)開始跨度標(biāo)簽,然后在鍵長(zhǎng)之后插入一個(gè)結(jié)束跨度標(biāo)簽。
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) +‘<span class=”qualifier”>’ +sentence.slice(index, index + key.length) +“</span>” +sentence.slice(index + key.length);} });With that working, it’s starting to look more and more like the Hemingway editor.
有了這項(xiàng)工作,它開始看起來越來越像海明威編輯器。
The last piece of the highlighting puzzle to implement was the passive voice. Hemingway used a 30 line function to find all of the passive phrases. I chose to use most of the logic that Hemingway implemented, but order the process differently. They looked to find any words that were in a list (is, are, was, were, be, been, being) and then checked whether the next word ended in ‘ed’.
突出顯示難題的最后一部分是被動(dòng)語態(tài)。 海明威使用30行函數(shù)查找所有被動(dòng)短語。 我選擇使用海明威實(shí)現(xiàn)的大多數(shù)邏輯,但是對(duì)過程的排序不同。 他們尋找找到列表中的任何單詞(是,曾經(jīng),曾經(jīng),曾經(jīng),是,曾經(jīng),存在),然后檢查下一個(gè)單詞是否以“ ed”結(jié)尾。
I looped though each of the words in a sentence and checked if they ended in ‘ed’. For every ‘ed’ word I found, I checked whether the previous word was in the list of pre-words. This seemed much simpler, but may be less performant.
我遍歷句子中的每個(gè)單詞,并檢查它們是否以“ ed”結(jié)尾。 對(duì)于找到的每個(gè)“ ed”單詞,我都會(huì)檢查前一個(gè)單詞是否在預(yù)單詞列表中。 這看似簡(jiǎn)單得多,但性能可能較差。
With that working I had an app that highlighted everything I wanted. This is my MVP.
通過這項(xiàng)工作,我有了一個(gè)突出顯示我想要的一切的應(yīng)用程序。 這是我的MVP。
然后我遇到了一個(gè)問題 (Then I hit a problem)
As I was writing this post I realised that there were two huge bugs in my code.
當(dāng)我寫這篇文章時(shí),我意識(shí)到我的代碼中有兩個(gè)巨大的錯(cuò)誤。
// from getQualifier and getComplex let index = sentence.toLowerCase().indexOf(key); // from getPassive let index = words.indexOf(match);These will only ever find the first instance of the key or match. Here is an example of the results this code will produce.
這些只會(huì)找到鍵或匹配項(xiàng)的第一個(gè)實(shí)例。 這是此代碼將產(chǎn)生的結(jié)果的示例。
‘Perhaps’ and ‘been marked’ should have been highlighted twice each but they aren’t.
“也許”和“被標(biāo)記”應(yīng)分別高亮兩次,但不是。
To fix the bug in getQualifier and getComplex, I decided to use recursion. I created a findAndSpan function which uses .indexOf() to find the first instance of the word or phrase. It splits the sentence into 3 parts: before the phrase, the phrase, after the phrase. The recursion works by passing the ‘a(chǎn)fter the phrase’ string back into the function. This will continue until there are no more instances of the phrase, where the string will just be passed back.
為了修復(fù)getQualifier和getComplex中的錯(cuò)誤,我決定使用遞歸。 我創(chuàng)建了一個(gè)findAndSpan函數(shù),該函數(shù)使用。 indexOf()查找單詞或短語的第一個(gè)實(shí)例。 它將句子分為三部分:短語之前,短語,短語之后。 遞歸通過將“短語后”字符串傳遞回函數(shù)來工作。 這將繼續(xù)進(jìn)行,直到不再有該短語的實(shí)例為止,在該實(shí)例中該字符串將被傳遞回去。
function findAndSpan(sentence, string, type) {let index = sentence.toLowerCase().indexOf(key);if (index >= 0) {sentence =sentence.slice(0, index) +`<span class="${type}">` +sentence.slice(index, index + key.length) +"</span>" +findAndSpan(sentence.slice(index + key.length), key,type);}return sentence; }Something very similar had to be done for the passive voice. The recursion was in an almost identical pattern, passing the leftover array items instead of the leftover string. The result of the recursion call was spread into an array that was then returned. Now the app can deal with repeated adverbs, qualifiers, complex phrases and passive voice uses.
對(duì)于被動(dòng)語音,必須做一些非常相似的事情。 遞歸以幾乎相同的模式進(jìn)行,傳遞剩余的數(shù)組項(xiàng)而不是剩余的字符串。 遞歸調(diào)用的結(jié)果被傳播到一個(gè)數(shù)組中,然后返回該數(shù)組。 現(xiàn)在,該應(yīng)用程序可以處理重復(fù)的副詞,限定詞,復(fù)雜的短語和被動(dòng)語音用法。
統(tǒng)計(jì)計(jì)數(shù)器 (Statistics Counter)
The last thing that I wanted to get working was the nice line of boxes informing you on how many adverbs or complex words you’d used.
我要開始工作的最后一件事是用漂亮的方框來告知您使用了多少個(gè)副詞或復(fù)雜詞。
To store the data I created an object with keys for each of the parameters I wanted to count. I started by having this variable as a global variable but knew I would have to change that later.
為了存儲(chǔ)數(shù)據(jù),我為每個(gè)要計(jì)數(shù)的參數(shù)創(chuàng)建了一個(gè)帶有鍵的對(duì)象。 我首先將此變量作為全局變量,但是知道以后必須更改它。
Now I had to populate the values. This was done by incrementing the value every time it was found.
現(xiàn)在,我必須填充值。 這是通過在每次找到該值時(shí)增加該值來完成的。
data.sentences += sentence.length or data.adverbs += 1The values needed to be reset every time the scan was run to make sure that values didn’t continuously increase.
每次運(yùn)行掃描時(shí)都需要重置這些值,以確保這些值不會(huì)持續(xù)增加。
With the values I needed, I had to get them rendering on the screen. I altered the structure of the html file so that the input box and output area were in a div on the left, leaving a right div for the counters. These counters are empty divs with an appropriate id and class as well as a ‘counter’ class.
有了我需要的值,我不得不將它們呈現(xiàn)在屏幕上。 我更改了html文件的結(jié)構(gòu),以使輸入框和輸出區(qū)域位于左側(cè)的div中,為計(jì)數(shù)器保留了右側(cè)的div。 這些計(jì)數(shù)器是具有適當(dāng)ID和類以及“計(jì)數(shù)器”類的空div。
<div id=”adverb” class=”adverb counter”></div> <div id=”passive” class=”passive counter”></div> <div id=”complex” class=”complex counter”></div> <div id=”hardSentence” class=”hardSentence counter”></div> <div id=”veryHardSentence” class=”veryHardSentence counter”></div>With these divs, I used document.querySelector to set the inner html for each of the counters using the data that had been collected. With a little bit of styling of the ‘counter’ class, the web app was complete. Try it out here or look at my code here.
通過這些div,我使用document.querySelector使用已收集的數(shù)據(jù)為每個(gè)計(jì)數(shù)器設(shè)置內(nèi)部html。 通過對(duì)“ counter”類進(jìn)行一些樣式設(shè)置,該Web應(yīng)用程序就完整了。 在這里嘗試或在這里查看我的代碼。
翻譯自: https://www.freecodecamp.org/news/https-medium-com-samwcoding-deconstructing-the-hemingway-app-8098e22d878d/
乞力馬扎羅山 海明威
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的乞力马扎罗山 海明威_我如何对海明威编辑器(一种流行的写作应用程序)进行反向工程,并从泰国的海滩上构建了自己的数据库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css左右布局代码_如何使用CSS位置来
- 下一篇: 梦到和前男友吵架是什么意思啊