T-ZPKQ-pumice-admin-body-renderer-seam
State: closed/done · Impact: medium · Complexity: medium
Pumice’s admin detail page renders an entity body with marked and DOMPurify, and the host
carries a Vite alias block to make the admin layer’s optional peers resolve. This task makes the
admin layer renderer-agnostic through an injection seam, has pumice supply MdViewer, and
deletes the second markdown stack and the alias block.
| Location | Role today |
|---|---|
apps/pumice/packages/nuxt_admin_layer/app/pages/admin/[entity]/[id]/index.vue | The only render site: DOMPurify.sanitize(await marked.parse(body)) into parsedBody |
apps/pumice/packages/nuxt_admin_layer/package.json | marked and dompurify as optional peerDependencies |
apps/pumice/packages/nuxt_admin_layer/app/composables/ | useAdminEntity.ts, useAdminRegistry.ts |
apps/pumice/src-nuxt/package.json | marked, dompurify; @determined/ui by file: |
apps/pumice/src-nuxt/nuxt.config.ts | Extends the admin layer and @determined/ui; vite.resolve.alias for marked and dompurify |
apps/pumice/bun.lock | Isolated lockfile, checked by .github/workflows/lockfile-drift.yml |
Proposed
Section titled “Proposed”The admin layer exports AdminBodyRendererKey (an InjectionKey for a Vue component taking
source: string) from a new useAdminBodyRenderer.ts. The detail page renders
<component :is="bodyRenderer" :source="body" /> when a renderer is provided and an escaped
<pre> otherwise. Pumice provides MdViewer from a client plugin. marked and dompurify
leave both package.json files, the alias block is deleted, @sksizer/markdown-ui is wired by
file: with overrides for its workspace:* transitives, and bun.lock is regenerated.
Approach
Section titled “Approach”- Admin layer: add
app/composables/useAdminBodyRenderer.tsexporting the injection key and auseAdminBodyRenderer()that returns the injected component ornull; rewrite the body section of[id]/index.vue; removemarked/dompurifyfrompeerDependenciesandpeerDependenciesMeta. - Pumice
src-nuxt/package.json: add@sksizer/markdown-ui,@sksizer/obsidian-md,@sksizer/obsidian-editor,@sksizer/markdown-utilbyfile:with matchingoverrides; deletemarked,dompurify. src-nuxt/nuxt.config.ts: add the layer toextendsafter the admin layer; delete thevite.resolve.aliasblock; addvite.resolve.dedupeforvue,@codemirror/state,@codemirror/view,@lezer/common; addoptimizeDeps.include: ['unified', 'extend', 'debug']as SDF does.- Add
src-nuxt/app/plugins/admin-body-renderer.tsprovidingMdViewerunder the key. cd apps/pumice && bun install; commitbun.lock;bun install --frozen-lockfile.- Verify:
bun run typecheck,bun run test:stories,bun run test:e2einsrc-nuxt;nuxi analyzeshows nomarkedchunk; an admin detail page with a fence and a table in light and dark;moon run :check :test --affected. Flip the pumice row of the duplicates ledger indocs/LIBRARIES.md.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
apps/pumice/packages/nuxt_admin_layer/app/composables/useAdminBodyRenderer.ts | new | Injection key and accessor |
apps/pumice/packages/nuxt_admin_layer/app/pages/admin/[entity]/[id]/index.vue | modify | Render through the injected component; delete marked/DOMPurify |
apps/pumice/packages/nuxt_admin_layer/package.json | modify | Drop the optional peers |
apps/pumice/src-nuxt/package.json | modify | Layer and transitives by file: with overrides; delete marked, dompurify |
apps/pumice/src-nuxt/nuxt.config.ts | modify | Extend the layer; delete alias block; dedupe and optimizeDeps |
apps/pumice/src-nuxt/app/plugins/admin-body-renderer.ts | new | Provides MdViewer |
apps/pumice/bun.lock | modify | Regenerated |
docs/LIBRARIES.md | modify | Pumice render-site row flips to resolved |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
grep -rn "marked\|dompurify" apps/pumice --include=package.json --include=nuxt.config.ts --include=*.vuereturns nothing, andapps/pumice/bun.lockhas nomarkedordompurifyentry. - AC-2:
[id]/index.vuecontains nov-htmlfed bymarked; with no renderer injected the body renders as an escaped<pre>(story or unit test). - AC-3:
bun run typecheck,test:storiesandtest:e2epass inapps/pumice/src-nuxt. - AC-4:
bun install --frozen-lockfilepasses inapps/pumice; the lockfile-drift workflow is green. - AC-5:
nuxi analyzelists nomarkedchunk; light and dark screenshots of an admin body are attached to the PR.
Out of scope
Section titled “Out of scope”TemplateEditor.vue; it does not render markdown.- Editing entity bodies in pumice.
- Moving the admin layer out of
apps/pumice/packages/.
Dependencies
Section titled “Dependencies”- T-A0HT-md-ui-layer-skeleton supplies
MdViewer. - Gate: T-8H57-obsidian-md-review-bug-triage sanitize and routing fixes; admin bodies are user-entered content.
D-7VMX-markdown-ecosystem-strategyd.10:markedanddompurifyare deleted from pumice.
Discovery context
Section titled “Discovery context”Member of milestone M-931L; wave 4a of D-K3EM-markdown-editor-chrome-and-plugin-environment.