- parseMarkdownWithCodeBlocks: capture full info-line (handles attrs like
```ocaml title="x", CRLF endings, trailing spaces) — fixes stray
backtick when fence had an info string.
- CodeBlock: registerCodeLanguageLoader() lets apps inject a Vite-processed
dynamic grammar loader (template-literal dynamic imports can't be code-split
inside a pre-bundled dep, so the loader must come from app source).
- language prop loosened to string; toCodeLanguage passes unknown ids through.
- Move lessonSegmentUtils.ts + parseLessonSegments.ts to lib/.