feat(06-01): add Nitro hook content:file:afterParse for reading-time injection

- Register `content:file:afterParse` hook to inject `wordCount` + `minutes`
  on every parsed markdown content object (D-19: 200 wpm, floor 1 min).
- Import pure util `countWordsInMinimalBody` from app/utils/countWords.
- Guard against non-`.md` files (defensive — hook fires on all sources).
- Values persist in @nuxt/content SQLite DB and are queryable via
  queryCollection thanks to matching Zod fields (content.config.ts).
This commit is contained in:
2026-04-22 09:02:23 +02:00
parent 63d0173b2d
commit 5397390be2
2 changed files with 26 additions and 3 deletions
+3 -3
View File
@@ -3,8 +3,8 @@ gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: Context gathered — ready for /gsd-plan-phase 6 status: Context gathered — ready for /gsd-plan-phase 6
last_updated: "2026-04-21T23:11:57.514Z" last_updated: "2026-04-22T06:55:05.535Z"
last_activity: 2026-04-21 last_activity: 2026-04-22
progress: progress:
total_phases: 8 total_phases: 8
completed_phases: 3 completed_phases: 3
@@ -26,7 +26,7 @@ progress:
Phase: Phase 6 — Blog Pages Phase: Phase 6 — Blog Pages
Plan: — Plan: —
Status: Context gathered — ready for /gsd-plan-phase 6 Status: Context gathered — ready for /gsd-plan-phase 6
Last activity: 2026-04-21 Last activity: 2026-04-22
Resume file: .planning/phases/06-blog-pages/06-UI-SPEC.md Resume file: .planning/phases/06-blog-pages/06-UI-SPEC.md
## Accumulated Context ## Accumulated Context
+23
View File
@@ -0,0 +1,23 @@
import { countWordsInMinimalBody } from '~/utils/countWords'
/**
* Nitro plugin: compute reading time for every markdown content file at parse time.
*
* Injects `wordCount` (number) and `minutes` (number, min 1) on the content object.
* Values are persisted in the @nuxt/content SQLite DB and queryable via queryCollection
* thanks to the matching Zod schema fields in content.config.ts (per D-18 + D-19).
*
* Hook reference: https://content.nuxt.com/docs/advanced/hooks
*/
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('content:file:afterParse', (ctx) => {
const { file, content } = ctx
// Only process markdown files (defensive — hook fires on all sources)
if (!file.id?.endsWith('.md')) return
const wordCount = countWordsInMinimalBody(content.body)
content.wordCount = wordCount
content.minutes = Math.max(1, Math.ceil(wordCount / 200)) // D-19: 200 wpm, floor 1 min
})
})