diff --git a/src/main.ts b/src/main.ts index 5cf97a8..cbc3293 100644 --- a/src/main.ts +++ b/src/main.ts @@ -33,7 +33,7 @@ export default class BetterWordCount extends Plugin { // Handle Statistics if (this.settings.collectStats) { - this.statsManager = new StatsManager(this.app.vault, this.app.workspace); + this.statsManager = new StatsManager(this.app.vault, this.app.workspace, this); } // Handle Status Bar diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index c01300c..b58c18a 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -2,6 +2,7 @@ export enum MetricCounter { words, characters, sentences, + pages, files, } @@ -38,6 +39,7 @@ export interface BetterWordCountSettings { altBar: StatusBarItem[]; countComments: boolean; collectStats: boolean; + pageWords: number; } export const DEFAULT_SETTINGS: BetterWordCountSettings = { @@ -71,4 +73,5 @@ export const DEFAULT_SETTINGS: BetterWordCountSettings = { ], countComments: false, collectStats: false, + pageWords: 300, }; diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 0e55833..a6aa43b 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -1,4 +1,4 @@ -import { App, PluginSettingTab, Setting, ToggleComponent } from "obsidian"; +import { App, PluginSettingTab, Setting, ToggleComponent, TextComponent } from "obsidian"; import type BetterWordCount from "src/main"; import { addStatusBarSettings } from "./StatusBarSettings"; @@ -37,6 +37,18 @@ export default class BetterWordCountSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }); }); + new Setting(containerEl) + .setName("Page Word Count") + .setDesc("Set how many words count as one \"page\"") + .addText((text: TextComponent) => { + text.inputEl.type = "number"; + text.setPlaceholder("300"); + text.setValue(this.plugin.settings.pageWords.toString()); + text.onChange(async (value: string) => { + this.plugin.settings.pageWords = parseInt(value); + await this.plugin.saveSettings(); + }); + }); // Status Bar Settings addStatusBarSettings(this.plugin, containerEl); diff --git a/src/settings/StatusBarSettings.svelte b/src/settings/StatusBarSettings.svelte index 9e2843a..6031454 100644 --- a/src/settings/StatusBarSettings.svelte +++ b/src/settings/StatusBarSettings.svelte @@ -18,6 +18,8 @@ return "Chars in Note" case MetricCounter.sentences: return "Sentences in Note" + case MetricCounter.pages: + return "Pages in Note" case MetricCounter.files: return "Total Notes" } @@ -29,6 +31,8 @@ return "Daily Chars" case MetricCounter.sentences: return "Daily Sentences" + case MetricCounter.pages: + return "Daily Pages" case MetricCounter.files: return "Total Notes" } @@ -40,6 +44,8 @@ return "Total Chars" case MetricCounter.sentences: return "Total Sentences" + case MetricCounter.pages: + return "Total Pages" case MetricCounter.files: return "Total Notes" } @@ -181,6 +187,7 @@ + @@ -348,6 +355,7 @@ + diff --git a/src/stats/Stats.ts b/src/stats/Stats.ts index 5209bb3..38a69aa 100644 --- a/src/stats/Stats.ts +++ b/src/stats/Stats.ts @@ -9,10 +9,12 @@ export interface Day { words: number; characters: number; sentences: number; + pages: number; files: number; totalWords: number; totalCharacters: number; totalSentences: number; + totalPages: number; } export type ModifiedFiles = Record; @@ -21,6 +23,7 @@ export interface FileStat { words: CountDiff; characters: CountDiff; sentences: CountDiff; + pages: CountDiff; } export interface CountDiff { diff --git a/src/stats/StatsManager.ts b/src/stats/StatsManager.ts index d96db15..59fad1e 100644 --- a/src/stats/StatsManager.ts +++ b/src/stats/StatsManager.ts @@ -1,23 +1,27 @@ import { debounce, Debouncer, TFile, Vault, Workspace } from "obsidian"; +import type BetterWordCount from "../main"; import { STATS_FILE } from "../constants"; import type { Day, VaultStatistics } from "./Stats"; import moment from "moment"; import { getCharacterCount, getSentenceCount, + getPageCount, getWordCount, } from "../utils/StatUtils"; export default class StatsManager { private vault: Vault; private workspace: Workspace; + private plugin: BetterWordCount; private vaultStats: VaultStatistics; private today: string; public debounceChange; - constructor(vault: Vault, workspace: Workspace) { + constructor(vault: Vault, workspace: Workspace, plugin: BetterWordCount) { this.vault = vault; this.workspace = workspace; + this.plugin = plugin; this.debounceChange = debounce( (text: string) => this.change(text), 50, @@ -76,15 +80,18 @@ export default class StatsManager { const totalWords = await this.calcTotalWords(); const totalCharacters = await this.calcTotalCharacters(); const totalSentences = await this.calcTotalSentences(); + const totalPages = await this.calcTotalPages(); const newDay: Day = { words: 0, characters: 0, sentences: 0, + pages: 0, files: 0, totalWords: totalWords, totalCharacters: totalCharacters, totalSentences: totalSentences, + totalPages: totalPages, }; this.vaultStats.modifiedFiles = {}; @@ -97,6 +104,8 @@ export default class StatsManager { const currentWords = getWordCount(text); const currentCharacters = getCharacterCount(text); const currentSentences = getSentenceCount(text); + const currentPages = getPageCount(text, this.plugin.settings.pageWords); + if ( this.vaultStats.history.hasOwnProperty(this.today) && this.today === moment().format("YYYY-MM-DD") @@ -110,9 +119,12 @@ export default class StatsManager { currentCharacters - modFiles[fileName].characters.current; this.vaultStats.history[this.today].totalSentences += currentSentences - modFiles[fileName].sentences.current; + this.vaultStats.history[this.today].totalPages += + currentPages - modFiles[fileName].pages.current; modFiles[fileName].words.current = currentWords; modFiles[fileName].characters.current = currentCharacters; modFiles[fileName].sentences.current = currentSentences; + modFiles[fileName].pages.current = currentPages; } else { modFiles[fileName] = { words: { @@ -127,6 +139,10 @@ export default class StatsManager { initial: currentSentences, current: currentSentences, }, + pages: { + initial: currentPages, + current: currentPages, + }, }; } @@ -145,10 +161,16 @@ export default class StatsManager { Math.max(0, counts.sentences.current - counts.sentences.initial) ) .reduce((a, b) => a + b, 0); + const pages = Object.values(modFiles) + .map((counts) => + Math.max(0, counts.pages.current - counts.pages.initial) + ) + .reduce((a, b) => a + b, 0); this.vaultStats.history[this.today].words = words; this.vaultStats.history[this.today].characters = characters; this.vaultStats.history[this.today].sentences = sentences; + this.vaultStats.history[this.today].pages = pages; this.vaultStats.history[this.today].files = this.getTotalFiles(); await this.update(); @@ -167,6 +189,7 @@ export default class StatsManager { todayHist.totalWords = await this.calcTotalWords(); todayHist.totalCharacters = await this.calcTotalCharacters(); todayHist.totalSentences = await this.calcTotalSentences(); + todayHist.totalPages = await this.calcTotalPages(); this.update(); } else { this.updateToday(); @@ -211,6 +234,20 @@ export default class StatsManager { return sentence; } + + private async calcTotalPages(): Promise { + let pages = 0; + + const files = this.vault.getFiles(); + for (const i in files) { + const file = files[i]; + if (file.extension === "md") { + pages += getPageCount(await this.vault.cachedRead(file), this.plugin.settings.pageWords); + } + } + + return pages; + } public getDailyWords(): number { return this.vaultStats.history[this.today].words; @@ -224,6 +261,10 @@ export default class StatsManager { return this.vaultStats.history[this.today].sentences; } + public getDailyPages(): number { + return this.vaultStats.history[this.today].pages; + } + public getTotalFiles(): number { return this.vault.getMarkdownFiles().length; } @@ -242,4 +283,9 @@ export default class StatsManager { if (!this.vaultStats) return await this.calcTotalSentences(); return this.vaultStats.history[this.today].totalSentences; } + + public async getTotalPages(): Promise { + if (!this.vaultStats) return await this.calcTotalPages(); + return this.vaultStats.history[this.today].totalPages; + } } diff --git a/src/status/StatusBar.ts b/src/status/StatusBar.ts index 7d40bfc..da952c6 100644 --- a/src/status/StatusBar.ts +++ b/src/status/StatusBar.ts @@ -4,6 +4,7 @@ import { getWordCount, getCharacterCount, getSentenceCount, + getPageCount, } from "src/utils/StatUtils"; import { debounce } from "obsidian"; @@ -107,6 +108,26 @@ export default class StatusBar { : 0)); break; } + } else if (metric.counter === MetricCounter.pages) { + switch (metric.type) { + case MetricType.file: + display = display + getPageCount(text, this.plugin.settings.pageWords); + break; + case MetricType.daily: + display = + display + + (this.plugin.settings.collectStats + ? this.plugin.statsManager.getDailyPages() + : 0); + break; + case MetricType.total: + display = + display + + (await (this.plugin.settings.collectStats + ? this.plugin.statsManager.getTotalPages() + : 0)); + break; + } } else if (metric.counter === MetricCounter.files) { switch (metric.type) { case MetricType.file: @@ -209,6 +230,26 @@ export default class StatusBar { : 0)); break; } + } else if (metric.counter === MetricCounter.pages) { + switch (metric.type) { + case MetricType.file: + display = display + 0; + break; + case MetricType.daily: + display = + display + + (this.plugin.settings.collectStats + ? this.plugin.statsManager.getDailyPages() + : 0); + break; + case MetricType.total: + display = + display + + (await (this.plugin.settings.collectStats + ? this.plugin.statsManager.getTotalPages() + : 0)); + break; + } } else if (metric.counter === MetricCounter.files) { switch (metric.type) { case MetricType.file: diff --git a/src/utils/StatUtils.ts b/src/utils/StatUtils.ts index eddaa6d..2d23966 100644 --- a/src/utils/StatUtils.ts +++ b/src/utils/StatUtils.ts @@ -37,6 +37,10 @@ export function getSentenceCount(text: string): number { return sentences; } +export function getPageCount(text: string, pageWords: number): number { + return parseFloat((getWordCount(text) / pageWords).toFixed(1)); +} + export function getTotalFileCount(vault: Vault): number { return vault.getMarkdownFiles().length; }