diff --git a/src/extensions/word-counter/client.mjs b/src/extensions/word-counter/client.mjs
index 42e1f25..33d639f 100644
--- a/src/extensions/word-counter/client.mjs
+++ b/src/extensions/word-counter/client.mjs
@@ -4,65 +4,38 @@
* (https://notion-enhancer.github.io/) under the MIT license
*/
-const humanTime = (mins) => {
- let readable = "";
- if (1 <= mins || !mins) {
- readable += `${Math.floor(mins)} min`;
- if (2 <= mins) readable += "s";
- }
- const secs = Math.round((mins % 1) * 60);
- if (1 <= secs) {
- if (1 <= mins) readable += " ";
- readable += `${secs} sec`;
- if (2 <= secs) readable += "s";
- }
- return readable;
-};
-
-function Stat(props, ...children) {
- const { html } = globalThis.__enhancerApi,
- $stat = html`
- ${children}
-
`;
- $stat.addEventListener("click", () => {
- navigator.clipboard.writeText($stat.innerText);
- });
- return $stat;
-}
+import { Stat } from "./islands/Stat.mjs";
+import { PanelDescription } from "../outliner/islands/PanelDescription.mjs";
export default async (api, db) => {
const { html, debounce, addMutationListener, addPanelView } = api,
readingSpeed = await db.get("readingSpeed"),
speakingSpeed = await db.get("speakingSpeed"),
- $wordCount = html`0`,
- $characterCount = html`0`,
- $sentenceCount = html`0`,
- $blockCount = html`0`,
- $readingTime = html`${humanTime(0)}`,
- $speakingTime = html`${humanTime(0)}`,
- page = ".notion-page-content";
+ page = ".notion-page-content",
+ humanReadableTime = (mins) => {
+ let readable = "";
+ if (isNaN(mins)) mins = 0;
+ const secs = Math.round((mins % 1) * 60);
+ mins = Math.floor(mins);
+ if (mins) readable = `${mins} min${mins === 1 ? "" : "s"}`;
+ if (secs && mins) readable += " ";
+ if (secs || !mins) readable += `${secs} sec${secs === 1 ? "" : "s"}`;
+ return readable;
+ };
+
+ const $wordCount = html`<${Stat} unit="word" countable />`,
+ $characterCount = html`<${Stat} unit="character" countable />`,
+ $sentenceCount = html`<${Stat} unit="sentence" countable />`,
+ $blockCount = html`<${Stat} unit="block" countable />`,
+ $readingTime = html`<${Stat} unit="reading time" />`,
+ $speakingTime = html`<${Stat} unit="speaking time" />`;
addPanelView({
title: "Word Counter",
$icon: "type",
$view: html`
-
- Click on a stat to copy it.
-
- <${Stat}>${$wordCount} words/>
- <${Stat}>${$characterCount} characters/>
- <${Stat}>${$sentenceCount} sentences/>
- <${Stat}>${$blockCount} blocks/>
- <${Stat}>${$readingTime} reading time/>
- <${Stat}>${$speakingTime} speaking time/>
+ <${PanelDescription}>Click on a stat to copy it./>
+ ${$wordCount}${$characterCount}${$sentenceCount}${$blockCount}
+ ${$readingTime}${$speakingTime}
`,
});
@@ -71,13 +44,15 @@ export default async (api, db) => {
if (!document.contains($page)) $page = document.querySelector(page);
if (!$page) return;
const text = $page.innerText,
- words = text.split(/[^\w]+/).length;
- $wordCount.innerText = words;
- $characterCount.innerText = text.length;
- $sentenceCount.innerText = text.split(".").filter((s) => s.trim()).length;
- $blockCount.innerText = $page.querySelectorAll("[data-block-id]").length;
- $readingTime.innerText = humanTime(words / readingSpeed);
- $speakingTime.innerText = humanTime(words / speakingSpeed);
+ words = text.split(/[^\w]+/).length,
+ sentences = text.split(".").filter((s) => s.trim()).length,
+ blocks = $page.querySelectorAll("[data-block-id]").length;
+ $wordCount.setCount(words);
+ $characterCount.setCount(text.length);
+ $sentenceCount.setCount(sentences);
+ $blockCount.setCount(blocks);
+ $readingTime.setCount(humanReadableTime(words / readingSpeed));
+ $speakingTime.setCount(humanReadableTime(words / speakingSpeed));
});
addMutationListener(page, updateStats);
updateStats();
diff --git a/src/extensions/word-counter/islands/Stat.mjs b/src/extensions/word-counter/islands/Stat.mjs
new file mode 100644
index 0000000..955166a
--- /dev/null
+++ b/src/extensions/word-counter/islands/Stat.mjs
@@ -0,0 +1,31 @@
+/**
+ * notion-enhancer: word-counter
+ * (c) 2024 dragonwocky (https://dragonwocky.me/)
+ * (https://notion-enhancer.github.io/) under the MIT license
+ */
+
+function Stat({ unit, countable, ...props }, ...children) {
+ const { html } = globalThis.__enhancerApi,
+ $count = html``,
+ $unit = html``,
+ $stat = html`
+ ${$count} ${$unit}
+
`;
+ $stat.setCount = (count) => {
+ $count.innerText = count;
+ const pluralise = countable && typeof count === "number" && count !== 1;
+ $unit.innerText = pluralise ? `${unit}s` : unit;
+ };
+ $stat.addEventListener("click", () => {
+ navigator.clipboard.writeText($stat.innerText);
+ });
+ return $stat;
+}
+
+export { Stat };