From dd9ce6e8b4319f92b8f13f24793a9adab64d0f6d Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Wed, 22 Apr 2026 09:04:53 +0200 Subject: [PATCH] feat(06-01): add useReadingTime composable fallback (200 wpm) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pure synchronous helper returning minutes (>= 1) from either a pre-computed word count (number) or raw text (string, tokenized on whitespace). - Client-side safety net when `article.minutes` isn't yet populated (e.g., dev hot-reload before the Nitro hook re-parsed). Source of truth remains the Nitro `content:file:afterParse` hook (D-19). - Same 200 wpm formula as server-side hook — ensures listing ↔ article parity. - Auto-imported by Nuxt thanks to `use*` naming convention. --- app/composables/useReadingTime.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 app/composables/useReadingTime.ts diff --git a/app/composables/useReadingTime.ts b/app/composables/useReadingTime.ts new file mode 100644 index 0000000..e67943d --- /dev/null +++ b/app/composables/useReadingTime.ts @@ -0,0 +1,17 @@ +/** + * Fallback reading-time helper when `article.minutes` is not available + * (e.g., dev hot-reload before the Nitro hook has re-parsed). + * + * Source of truth = server/plugins/reading-time.ts + content.config.ts schema. + * This is only a client-side safety net (per D-19). + * + * @param wordCountOrText number (word count already computed) OR string (raw text to tokenize) + * @returns minutes (>= 1), rounded up, using 200 words per minute + */ +export function useReadingTime(wordCountOrText: number | string): number { + if (typeof wordCountOrText === 'number') { + return Math.max(1, Math.ceil(wordCountOrText / 200)) + } + const count = wordCountOrText.trim().split(/\s+/).filter(Boolean).length + return Math.max(1, Math.ceil(count / 200)) +}