diff --git a/src/pages/log.mdo b/src/pages/log.mdo index 4469e9cda08e6f670318cfab3686e32c68419537..0b3fcff0aa62ea751b366917d10b99144b80d827 100644 --- a/src/pages/log.mdo +++ b/src/pages/log.mdo @@ -16,7 +16,8 @@ static const repo = "${repo}"; [ts lie detector]: https://git.paperclover.net/clo/ts-lie-detector [evil inc]: https://evil.inc/ [history of japan reanimated]: /history-of-japan-reanimated -[react mutation]: /history-of-japan-reanimated +[react mutation]: http://jsr.io/@clo/react-mutation +[react markdown]: http://jsr.io/@clo/react-markdown [HOTEWIG reanimated]: /hotewig-reanimated [clover creative control]: https://git.paperclover.net/clo/creative-control [markodown]: https://git.paperclover.net/clo/markodown @@ -29,6 +30,83 @@ static const repo = "${repo}"; these are like mini blog posts, but more in generally just what the heck i'm up to. +## 2026-03-20 + +tags: [react markdown] + +i published a new library named `@clo/react-markdown`. originally, i wanted to +have my own version of the `streamdown` package from vercel. but i didn't +realize how much of a loser company they all are. i wasn't even trying and i +made a library like a hundred times better and simpler than theres. because of +the awesome success here, instead of calling mine "memo markdown", i just said +"yea, this covers every markdown use case for react" and called it React Markdown. + +you can install it from the JSR: + +```sh +npx jsr add @clo/react-markdown +pnpm add jsr:@clo/react-markdown +``` + +there are two main features that i deliver on: + +- predicting close tokens for sequences like `hello **world`, appending `**` + - streamdown has this too, but many many cases are not considered. while + theirs is extensible and mine isn't, i don't think you'll need to extend + my markdown predictor. +- component memoization. all block and inline components will preserve their + state, even as adjacent content changes. this is done to preserve remounts + for things like custom `` tags or other components. (for example, if a + custom `` fetches previewing data and provides a hover card, that card + won't flicker). + +copying some architecture notes from the readme, the memoizer is performant +from the following tricks: + +- Using proper `React.memo()` calls. Obviously. +- Prediction is implemented in a stateful way that only parses the tail end of + the document, marking how much of the document is stable and where possible + incomplete syntax may live. Since prediction only applies at the end, changing + text midway through can invalidate the whole predictor. +- Separate the parsed document into "blocks", noting the source location of + where each block lives. +- Only start parsing after the first changed character, rounded to the nearest + block. In the append-only stream, this essentially means the last two blocks + are the only things being re-parsed. +- Similarly, run AST transforms only on the changed data. This step has a couple + of slow paths for when reference link definitions are added or edited, since + it means any places that might have used a reference link may now have to + reflect it. +- After all that, a special AST -> React node transform is used that diffs the + new ast with the last ast, reusing React nodes whenever possible. It supports + nested children as well as re-ordering top level blocks. This is what prevents + most rerenders and is the "secret sauce". + +## 2026-03-18 + +tags: [progress.ts] + +laser hair removal is awesome btw. organizing things at home slowly. more work +on the progress library, trying to handle every edge case possible for the log +widget system. + +when it is done, a code snippet like this will work. + +```ts +using node = progress.start("some action"); +for await (const token of stream) { + // correctly interweave progress TUI with partial log lines + process.stderr.write(token); +} +``` + +the log system injects into `process` to ensure it plays nice, but there is +only a fast path on stdout (since the main log messages uses stdout). stderr +gets to use the crazy `getDrawLock` API i'm cooking up internally. + +after all of this works and is reliable, there are some more things i have to +tidy, but then the progress blog post can be written and reviewed for realsies. + ## 2026-03-16 just chilling. at work i replaced `bun install` with `pnpm`. pretty peak. in the