Class: MaquinaStream::Document
- Inherits:
-
Object
- Object
- MaquinaStream::Document
- Defined in:
- lib/maquina_stream/document.rb
Overview
Splits a rendered message into top-level blocks, and decides which of them are safe to freeze.
document = MaquinaStream::Document.new(markdown, config: config, sid: "m8f21")
document.blocks # every top-level block, in order
document.sealed_blocks # frozen, never re-sent
document.open_block # the tail, patched on every frame
The whole buffer is rendered once and then sliced. Blocks are never rendered in isolation: a block that mentions [docs] needs the link reference definition that lives at the bottom of the message, and rendering it alone silently loses it.
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
The Configuration it reads —
seal_lagin particular. -
#markdown ⇒ Object
readonly
The raw markdown this document was built from.
-
#mode ⇒ Object
readonly
The render mode passed through to Renderer, one of Renderer::MODES.
-
#sid ⇒ Object
readonly
The stream id every block id is prefixed with, or nil for an anonymous render.
Instance Method Summary collapse
-
#blocks ⇒ Object
Every top-level Block, in document order, each already stamped with its id and digest.
-
#html ⇒ Object
The whole document as one rendered HTML string, before it is sliced into blocks.
-
#initialize(markdown, config: MaquinaStream.config, sid: nil, mode: :streaming) ⇒ Document
constructor
Builds a document over one markdown buffer.
-
#manifest_entries ⇒ Object
[[id, digest], …]for the sealed blocks. -
#open_block ⇒ Object
The last block — the tail the model is currently writing into.
-
#seal_pointer ⇒ Object
How far sealing reached, as an index into #blocks.
-
#sealed_blocks ⇒ Object
Sealed blocks trail the tail by config.seal_lag.
-
#unsealed_blocks ⇒ Object
The blocks behind the seal pointer: still able to change, and therefore still eligible for a patch on the next frame.
Constructor Details
#initialize(markdown, config: MaquinaStream.config, sid: nil, mode: :streaming) ⇒ Document
Builds a document over one markdown buffer.
sid: is the record's maquina_stream_id. Pass it: block ids are built
from it, and a document rendered without one produces ids
(ms-b0, ms-b1) that collide the moment two messages share a page.
Nothing is rendered until #blocks or #html is called.
39 40 41 42 43 44 |
# File 'lib/maquina_stream/document.rb', line 39 def initialize(markdown, config: MaquinaStream.config, sid: nil, mode: :streaming) @markdown = markdown.to_s @config = config @sid = sid @mode = mode end |
Instance Attribute Details
#config ⇒ Object (readonly)
The Configuration it reads — seal_lag in particular.
23 24 25 |
# File 'lib/maquina_stream/document.rb', line 23 def config @config end |
#markdown ⇒ Object (readonly)
The raw markdown this document was built from.
20 21 22 |
# File 'lib/maquina_stream/document.rb', line 20 def markdown @markdown end |
#mode ⇒ Object (readonly)
The render mode passed through to Renderer, one of Renderer::MODES.
30 31 32 |
# File 'lib/maquina_stream/document.rb', line 30 def mode @mode end |
#sid ⇒ Object (readonly)
The stream id every block id is prefixed with, or nil for an anonymous render.
27 28 29 |
# File 'lib/maquina_stream/document.rb', line 27 def sid @sid end |
Instance Method Details
#blocks ⇒ Object
Every top-level Block, in document order, each already stamped with its id and digest. Memoized: the whole buffer is rendered once, on the first call.
49 50 51 |
# File 'lib/maquina_stream/document.rb', line 49 def blocks @blocks ||= build_blocks end |
#html ⇒ Object
The whole document as one rendered HTML string, before it is sliced into blocks. Memoized.
87 88 89 |
# File 'lib/maquina_stream/document.rb', line 87 def html @html ||= Renderer.call(markdown, mode: mode, config: config) end |
#manifest_entries ⇒ Object
[[id, digest], …] for the sealed blocks. What Manifest is built from.
92 93 94 |
# File 'lib/maquina_stream/document.rb', line 92 def manifest_entries sealed_blocks.map(&:to_manifest_entry) end |
#open_block ⇒ Object
The last block — the tail the model is currently writing into.
81 82 83 |
# File 'lib/maquina_stream/document.rb', line 81 def open_block blocks.last end |
#seal_pointer ⇒ Object
How far sealing reached, as an index into #blocks. Sealing is a prefix, so this is both the count of sealed blocks and the position of the first unsealed one.
76 77 78 |
# File 'lib/maquina_stream/document.rb', line 76 def seal_pointer @seal_pointer ||= blocks.count(&:sealed?) end |
#sealed_blocks ⇒ Object
Sealed blocks trail the tail by config.seal_lag. Markdown reinterprets retroactively - a paragraph becomes a heading when its underline arrives, a table's delimiter row turns the line above into a header - so a block is only safe to freeze once enough later blocks exist that nothing can reach back into it.
The lag is not the whole story. A link reference definition resolves links in blocks arbitrarily far above it, so no fixed lag makes a block with an unresolved reference safe. The pointer stops there instead, and moves on once the definition arrives.
63 64 65 |
# File 'lib/maquina_stream/document.rb', line 63 def sealed_blocks blocks.first(seal_pointer) end |
#unsealed_blocks ⇒ Object
The blocks behind the seal pointer: still able to change, and therefore still eligible for a patch on the next frame.
69 70 71 |
# File 'lib/maquina_stream/document.rb', line 69 def unsealed_blocks blocks.drop(seal_pointer) end |