Various interests are served by abstracting diffs and diff presentation so that the unit of change is a "block" rather than a "line of text". An immediate application is sensible UI diffing of Jupyter notebooks. A related application is more scalable prose diffs.
This is not conceptually hard because we can transform a "list of blocks" into a "list of lines of text" by hashing each block (and this is what diff does internally anyway, more or less). There's just a lot of mapping and separation of concepts ("block content" vs "block hash" vs "text line"; "line number" vs "block identifier") that are currently conflated.
There may be some technical limits later -- for example, inlines are associated with a numeric "line number", not a freeform "block identifier". There may be a path out of this with clever mapping. In the case where the block is a 3D model and we want to attach an inline to a vertex or something we probably can't just do clever mapping, but this is a different flavor of abstraction; for now, we're only going as far as block lists with a well-defined one-dimensional order.
There's a support issue somewhere about inline on specific offsets within a line which might arise here, but hopefully that can be scoped separately. The ideal abstraction is that inlines have a "block identifier" (normally, a "line number") and then a separate "location within the block", which might be "characters 9-13" for a line of text or "<12, 34, 29>" for a 3D model.
My planned path is:
- Allow DocumentEngine to elect into diff rendering.
- Elect the image engine into diff rendering.
- Make the image engine emit a generic block list. Make the ChangesetParser render a block list though the Renderer.
- The "image stage" code moves to the image engine (or the block list if reuse is interesting).
- The "scaffolding" code moves to "renderer->renderBlockList()".
Then, in whatever order is easiest -- these steps don't have obvious dependencies:
- Between emission of the block list and rendering, diff the block list.
- Make inlines work on blocks emitted as part of a block list.
- Elect the Jupyter engine into diff rendering and emit Jupyter books as a block list.