chore(ui): replace showdown markdown renderer#936
Conversation
📝 WalkthroughWalkthroughThe PR migrates the frontend's markdown rendering library from Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts (1)
30-30: Migration looks correct; sanitization preserved.
new MarkdownIt({ html: true })paired withDOMPurify.sanitizekeeps the same trust model as the previous showdown setup (raw HTML allowed in source, then sanitized). The h2→h3 post-processing is retained.One thing worth a quick smoke test: showdown and markdown-it differ on a few defaults that can matter for changelog content:
linkifyis off by default in markdown-it, so bare URLs won’t auto-link (showdown’ssimplifiedAutoLinkwas also off by default, so likely no regression — but worth eyeballing the rendered changelog).- markdown-it uses CommonMark line-break semantics (a soft break renders as a space, not
<br>). Showdown sometimes inserted<br>for single line breaks. If release notes were authored relying on that, paragraphs may flow differently.If either becomes an issue, you can opt-in with:
Suggested options if rendering regresses
- private markdown = new MarkdownIt({ html: true }); + private markdown = new MarkdownIt({ html: true, linkify: true, breaks: true });Also applies to: 44-47
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts` at line 30, The MarkdownIt instance (private markdown = new MarkdownIt({ html: true })) may change rendering compared to showdown (notably link auto-linking and line-break handling); update the MarkdownIt options to explicitly opt into the behavior you need (e.g., enable linkify and/or breaks via its config) if the changelog rendering regresses, and run a smoke test of the version-changelog-dialog rendering (also update the other MarkdownIt initializations found in the same file where the h2→h3 post-processing is applied) to confirm output matches expectations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts`:
- Line 30: The MarkdownIt instance (private markdown = new MarkdownIt({ html:
true })) may change rendering compared to showdown (notably link auto-linking
and line-break handling); update the MarkdownIt options to explicitly opt into
the behavior you need (e.g., enable linkify and/or breaks via its config) if the
changelog rendering regresses, and run a smoke test of the
version-changelog-dialog rendering (also update the other MarkdownIt
initializations found in the same file where the h2→h3 post-processing is
applied) to confirm output matches expectations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 41d507b2-d818-4e4f-a2bd-9a2a7ba89abc
⛔ Files ignored due to path filters (1)
frontend/yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
frontend/angular.jsonfrontend/package.jsonfrontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
💤 Files with no reviewable changes (1)
- frontend/angular.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Test Suite / Backend Tests
- GitHub Check: Test Suite / Frontend Tests
- GitHub Check: Analyze (java-kotlin)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Frontend Lint Threshold Check
🧰 Additional context used
📓 Path-based instructions (4)
frontend/src/**/*.{ts,tsx,html,scss}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation in TypeScript, HTML, and SCSS in frontend code
Files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
frontend/src/**/*.component.ts
📄 CodeRabbit inference engine (AGENTS.md)
Keep Angular code on standalone components. Do not add NgModules in frontend code
Files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer inject() over constructor injection in frontend code
Files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
frontend/src/**/*.{ts,tsx,html}
📄 CodeRabbit inference engine (AGENTS.md)
frontend/src/**/*.{ts,tsx,html}: Follow frontend/eslint.config.js: component selectors use app-, directive selectors use app, and any is disallowed in frontend code
Put user-facing strings in Transloco files under frontend/src/i18n/
Files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
🧠 Learnings (4)
📚 Learning: 2026-04-22T01:56:39.495Z
Learnt from: CR
Repo: grimmory-tools/grimmory PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-22T01:56:39.495Z
Learning: Applies to frontend/src/**/*.{test,spec}.{ts,tsx} : Use Vitest for tests in frontend code
Applied to files:
frontend/package.json
📚 Learning: 2026-04-05T21:16:01.715Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 385
File: frontend/src/app/app.component.ts:55-56
Timestamp: 2026-04-05T21:16:01.715Z
Learning: When reviewing code in the Grimmory frontend (Angular), prefer modern Angular patterns. Specifically: (1) Prefer `DestroyRef` with `takeUntilDestroyed(destroyRef)` for teardown in Angular v16+ instead of manually tracking `Subscription` arrays and calling `unsubscribe()` in `ngOnDestroy()`. (2) Prefer `inject()` for dependency injection over constructor injection where appropriate. (3) Prefer Angular signals (e.g., `signal`, `computed`) over `BehaviorSubject`/`Observable` for state where signals/computed values fit the use case. Flag older patterns when they can be replaced with these modern equivalents without changing behavior.
Applied to files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
📚 Learning: 2026-04-07T09:28:09.587Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 393
File: frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts:255-263
Timestamp: 2026-04-07T09:28:09.587Z
Learning: In this Angular frontend (under frontend/src/app/), flag manual resource management/cleanup patterns when there is an Angular v16+ automatic alternative. Examples to prefer: (1) Instead of manually pairing document/window event listeners with stored cleanup functions (e.g., add/removeEventListener with mouseMoveCleanup/documentClickCleanup/keydownCleanup/touchCleanup fields), register teardown via DestroyRef.onDestroy(cleanupFn) (or equivalent Angular v16+ teardown mechanism). (2) Instead of storing Subscriptions in fields and explicitly unsubscribing in ngOnDestroy (e.g., annotationSaveSubscription/annotationCacheSubscription), use takeUntilDestroyed(destroyRef) (piped into the observable) or other Angular v16+ primitives. (3) If teardown is lifecycle-coupled and can be automated via DestroyRef/takeUntilDestroyed/signals (or other Angular v16+ mechanisms), prefer the automated approach over manual ngOnDestroy cleanup. Raise a review finding for the manual pattern and recommend the aut...
Applied to files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
📚 Learning: 2026-04-11T03:55:57.229Z
Learnt from: zachyale
Repo: grimmory-tools/grimmory PR: 439
File: frontend/src/app/features/series-browser/components/series-browser/series-browser.component.ts:178-196
Timestamp: 2026-04-11T03:55:57.229Z
Learning: In this Angular frontend (frontend/src/app/), prefer the team’s reactive i18n “signal/computed” pattern: (1) For individual reactive translated strings, use `translateSignal()` from `jsverse/transloco`. (2) For option/label arrays that must update on language switch, create a single `activeLang` signal with `toSignal(t.langChanges$, { initialValue: t.getActiveLang() })`, then derive the arrays as `computed()` signals that read `activeLang()`. This should avoid manual `langChanges$` subscriptions and any `ngOnDestroy` subscription cleanup; prefer this over subscribing in `ngOnInit` when implementing reactive localization.
Applied to files:
frontend/src/app/shared/layout/layout-menu/version-changelog-dialog/version-changelog-dialog.component.ts
🔇 Additional comments (1)
frontend/package.json (1)
48-48: Dependency swap looks clean.
markdown-it^14.1.1 and@types/markdown-it^14.1.2 added in correct sections;showdownand its types removed. This addresses the GHSA-rmmh-p597-ppvv vulnerability called out in#914.Also applies to: 73-73
Description
Linked Issue: Fixes #914
Screenshot below, I did a temp tweak to show all changelogs. Actual behaviour is unchanged.

Changes
npm auditSummary by CodeRabbit