Skip to content

feat(markdown): Render lesson Markdown to sanitized, cached HTML#90

Merged
ebouchut merged 3 commits into
devfrom
feat/markdown-rendering
Jul 12, 2026
Merged

feat(markdown): Render lesson Markdown to sanitized, cached HTML#90
ebouchut merged 3 commits into
devfrom
feat/markdown-rendering

Conversation

@ebouchut

@ebouchut ebouchut commented Jul 12, 2026

Copy link
Copy Markdown
Owner

@ebouchut ebouchut changed the title feat/markdown-rendering feat(markdown): Render lesson Markdown to sanitized, cached HTML Jul 12, 2026
@ebouchut ebouchut force-pushed the feat/course-lesson-domain branch from e0c5952 to 4ed7c36 Compare July 12, 2026 15:33
@ebouchut ebouchut force-pushed the feat/markdown-rendering branch from 567d675 to eebd3c6 Compare July 12, 2026 15:33
@ebouchut ebouchut self-assigned this Jul 12, 2026
@ebouchut ebouchut moved this to In Review in learn-dev-project Jul 12, 2026
@ebouchut ebouchut force-pushed the feat/course-lesson-domain branch from 4ed7c36 to 11e78cb Compare July 12, 2026 16:41
@ebouchut ebouchut force-pushed the feat/markdown-rendering branch from eebd3c6 to bb1c2e3 Compare July 12, 2026 16:41
@ebouchut ebouchut force-pushed the feat/course-lesson-domain branch from 11e78cb to 54630d2 Compare July 12, 2026 16:44
@ebouchut ebouchut force-pushed the feat/markdown-rendering branch from bb1c2e3 to 4cd8d21 Compare July 12, 2026 16:44
Base automatically changed from feat/course-lesson-domain to dev July 12, 2026 16:46
ebouchut added 3 commits July 12, 2026 18:47
Record the lesson Markdown rendering decision: commonmark-java (the
CommonMark reference implementation) converts, jsoup's allowlist
sanitizes the output because instructor content is untrusted input and
raw HTML passes through the renderer, and Spring Cache over Caffeine
memoizes the result keyed by the SHA-256 of the source (content
addressed, so entries cannot go stale). flexmark and a server-side
JavaScript renderer were considered and rejected as disproportionate
for v1.
Add commonmark (0.24.0), jsoup (1.21.1), spring-boot-starter-cache, and
the Boot-managed Caffeine, per ADR-0013. MarkdownRenderer parses and
renders the Markdown, then cleans the HTML through Safelist.relaxed()
plus the class attribute on code (language hints for a future syntax
highlighter): scripts, event handlers, and javascript: URLs do not
survive, whatever the lesson contains.

CacheConfig enables caching with a single renderedMarkdown cache capped
at 1000 entries; entries are keyed by the SHA-256 of the source, so an
edited lesson is a new key and no invalidation logic exists. Both
glossaries define Markdown, CommonMark, jsoup, and Caffeine, and the
tech stack gains a Content rendering section.

Fixes #35
Fixes #36
Fixes #37
Fixes #38
Boot a minimal context (CacheConfig plus the renderer, no database) so
Cacheable runs through the real proxy: common constructs render to HTML
with the language hint kept, hostile Markdown loses its script, event
handler, and javascript: URL, the second render of identical content
returns the cached instance itself, and blank content renders empty.
@ebouchut ebouchut force-pushed the feat/markdown-rendering branch from 4cd8d21 to 031c3c9 Compare July 12, 2026 16:47
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.94737% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.30%. Comparing base (3896cb0) to head (031c3c9).

Files with missing lines Patch % Lines
.../ericbouchut/learndev/course/MarkdownRenderer.java 73.33% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##                dev      #90      +/-   ##
============================================
- Coverage     81.49%   81.30%   -0.20%     
- Complexity       55       62       +7     
============================================
  Files            21       23       +2     
  Lines           227      246      +19     
  Branches         12       13       +1     
============================================
+ Hits            185      200      +15     
- Misses           30       32       +2     
- Partials         12       14       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ebouchut ebouchut merged commit 2d16b9a into dev Jul 12, 2026
11 checks passed
@ebouchut ebouchut deleted the feat/markdown-rendering branch July 12, 2026 16:49
@github-project-automation github-project-automation Bot moved this from In Review to Done in learn-dev-project Jul 12, 2026
@ebouchut ebouchut added the dwwm label Jul 12, 2026
@ebouchut ebouchut added this to the v0.9 - Code Freeze milestone Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant