Skip to content

Instantly share code, notes, and snippets.

@sigaloid
Last active May 25, 2022 08:23
Show Gist options
  • Save sigaloid/ed8bac1254fabcc89d2eb1c5d595f539 to your computer and use it in GitHub Desktop.
Save sigaloid/ed8bac1254fabcc89d2eb1c5d595f539 to your computer and use it in GitHub Desktop.
Trilium frontend JS that displays word count, char count, sentence count, reading and speaking time, unique word count, and hand-writing time (more soon?)
/*
* This defines a custom widget which displays number of words and characters in a current text note.
* To be activated for a given note, add label 'wordCount' to the note, you can also make it inheritable and thus activate it for the whole subtree.
*
* See it in action in "Books" and its subtree.
*/
const TPL = `<div style="contain: none; padding: 10px; border-top: 1px solid var(--main-border-color);">
<i>Word count: </i>
<strong><span class="word-count"></span></strong>
&nbsp;
<i>Character count: </i>
<strong><span class="character-count"></span></strong>
&nbsp;
<i>Sentence count: </i>
<strong><span class="sentence-count"></span></strong>
&nbsp;
<i>Reading time: </i>
<strong><span class="reading-time"></span></strong>
<i> sec </i>
&nbsp;
<i>Speaking time: </i>
<strong><span class="speaking-time"></span></strong>
<i> sec </i>
<br>
<i>Unique word count: </i>
<strong><span class="unique-word-count"></span></strong>
&nbsp;
<i>Hand-writing time:</i>
<strong><span class="writing-time"></span> minutes</strong>
</div`;
class WordCountWidget extends api.TabAwareWidget {
get position() { return 100; } // higher value means position towards the bottom/right
get parentWidget() { return 'center-pane'; }
doRender() {
this.$widget = $(TPL);
this.$wordCount = this.$widget.find('.word-count');
this.$characterCount = this.$widget.find('.character-count');
this.$sentenceCount = this.$widget.find('.sentence-count');
this.$readingTime = this.$widget.find('.reading-time');
this.$speakingTime = this.$widget.find('.speaking-time');
this.$uniqueWordCount = this.$widget.find('.unique-word-count');
this.$writingTime = this.$widget.find('.writing-time');
return this.$widget;
}
async refreshWithNote(note) {
if (note.type !== 'text' || !note.hasLabel('wordCount')) {
// show widget only on text notes and when marked with 'wordCount' label
this.toggleInt(false); // hide
return;
}
this.toggleInt(true); // display
const {content} = await note.getNoteComplement();
const text = $(content).text(); // get plain text only
const counts = this.getCounts(text);
this.$wordCount.text(counts.words);
this.$characterCount.text(counts.characters);
this.$sentenceCount.text(counts.sentences_count);
this.$readingTime.text(counts.reading);
this.$speakingTime.text(counts.speaking);
this.$uniqueWordCount.text(counts.unique_words);
this.$writingTime.text(counts.writing_time);
}
getCounts(text) {
const chunks = text
.split(/[\s-+:,/\\]+/)
.filter(chunk => chunk !== '');
let words;
if (chunks.length === 1 && chunks[0] === '') {
words = 0;
}
else {
words = chunks.length;
}
const characters = chunks.join('').length;
const sentences = text.split(/\s+[^.!?]*[.!?]/g);
const sentences_count = sentences.length;
const reading = Math.round((words / 275) * 60);
const speaking = Math.round((words / 180) * 60);
const unique_words = new Set(chunks.map(a=>a.toLowerCase())).size;
const writing_time = ((characters / 68)).toFixed(3);;
return {words, characters, sentences_count, reading, speaking, unique_words, writing_time};
}
async entitiesReloadedEvent({loadResults}) {
if (loadResults.isNoteContentReloaded(this.noteId)) {
this.refresh();
}
}
}
module.exports = new WordCountWidget();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment