Class: MaquinaStream::Block
- Inherits:
-
Object
- Object
- MaquinaStream::Block
- Defined in:
- lib/maquina_stream/block.rb
Overview
One top-level block of a message: the slice of raw markdown it came from, the HTML it rendered to, and whether it is safe to freeze.
The id is derived from the index and never from the content. Idiomorph keys on id, so a content-derived id turns every edit into a delete-and-recreate, which loses scroll position, animation state and anything the client owns.
Blocks come from Document. Building one by hand is possible but rarely useful: the id and digest a repair needs are stamped on during that split. Instances are immutable — #seal returns a new Block rather than mutating.
Instance Attribute Summary collapse
-
#html ⇒ Object
readonly
The rendered HTML for this block alone, including its own element and the
id,data-ms-blockanddata-ms-block-digestattributes. -
#index ⇒ Object
readonly
This block's position in the document, zero-based.
-
#line_range ⇒ Object
readonly
The Range of 1-based source lines this block covers.
-
#markdown ⇒ Object
readonly
The slice of raw markdown this block was rendered from.
-
#sid ⇒ Object
readonly
The stream id this block belongs to, or nil for an anonymous render.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Two blocks are equal when they hold the same index and the same HTML.
-
#digest ⇒ Object
Digest of the block's rendered CONTENT, not of the source and not of the whole element.
-
#hash ⇒ Object
Hashed on the same two fields #== compares.
-
#id ⇒ Object
The DOM id,
ms-<sid>-b<index>. -
#initialize(index:, markdown:, html:, line_range:, sid: nil, sealed: false, digest: nil) ⇒ Block
constructor
Builds a block.
-
#open? ⇒ Boolean
Whether this block can still change, and can therefore still be patched.
-
#seal ⇒ Object
A copy of this block, sealed.
-
#sealed? ⇒ Boolean
Whether this block is frozen — far enough behind the tail that nothing can reinterpret it, and therefore never re-broadcast.
-
#to_manifest_entry ⇒ Object
[id, digest]— one row of a Manifest, and the unit the client diffs its own DOM against.
Constructor Details
#initialize(index:, markdown:, html:, line_range:, sid: nil, sealed: false, digest: nil) ⇒ Block
Builds a block. Document does this; a host normally reads blocks rather than constructing them.
38 39 40 41 42 43 44 45 46 |
# File 'lib/maquina_stream/block.rb', line 38 def initialize(index:, markdown:, html:, line_range:, sid: nil, sealed: false, digest: nil) @index = index @markdown = markdown @html = html @line_range = line_range @sid = sid @sealed = sealed @digest = digest end |
Instance Attribute Details
#html ⇒ Object (readonly)
The rendered HTML for this block alone, including its own element and the
id, data-ms-block and data-ms-block-digest attributes.
26 27 28 |
# File 'lib/maquina_stream/block.rb', line 26 def html @html end |
#index ⇒ Object (readonly)
This block's position in the document, zero-based. The id is derived from it.
19 20 21 |
# File 'lib/maquina_stream/block.rb', line 19 def index @index end |
#line_range ⇒ Object (readonly)
The Range of 1-based source lines this block covers. Coverage has gaps — an HTML block reports no source position at all — so a block with no range of its own inherits the lines between its neighbours.
31 32 33 |
# File 'lib/maquina_stream/block.rb', line 31 def line_range @line_range end |
#markdown ⇒ Object (readonly)
The slice of raw markdown this block was rendered from.
22 23 24 |
# File 'lib/maquina_stream/block.rb', line 22 def markdown @markdown end |
#sid ⇒ Object (readonly)
The stream id this block belongs to, or nil for an anonymous render.
34 35 36 |
# File 'lib/maquina_stream/block.rb', line 34 def sid @sid end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Two blocks are equal when they hold the same index and the same HTML. Sealing is deliberately not part of it: a block that sealed between two frames is the same block, and the seal is a decision about it rather than a property of it.
91 92 93 |
# File 'lib/maquina_stream/block.rb', line 91 def ==(other) other.is_a?(Block) && other.index == index && other.html == html end |
#digest ⇒ Object
Digest of the block's rendered CONTENT, not of the source and not of the whole element.
The manifest compares what the browser actually has, so two different
sources that render alike need no repair between them. Element-level
attributes are excluded on purpose: a block gains data-ms-block-state
when it seals and loses data-ms-caret when the tail moves past it, and
neither changes what the block says. Digesting them would make every block
in every message fetch itself once, for nothing.
70 71 72 |
# File 'lib/maquina_stream/block.rb', line 70 def digest @digest ||= Digest::SHA256.hexdigest(html.to_s)[0, 16] end |
#hash ⇒ Object
Hashed on the same two fields #== compares.
97 |
# File 'lib/maquina_stream/block.rb', line 97 def hash = [index, html].hash |
#id ⇒ Object
The DOM id, ms-<sid>-b<index>. Index-derived, never content-derived:
idiomorph keys on it.
50 51 52 |
# File 'lib/maquina_stream/block.rb', line 50 def id sid ? "ms-#{sid}-b#{index}" : "ms-b#{index}" end |
#open? ⇒ Boolean
Whether this block can still change, and can therefore still be patched.
59 |
# File 'lib/maquina_stream/block.rb', line 59 def open? = !sealed? |
#seal ⇒ Object
A copy of this block, sealed. Returns a new Block; the receiver is unchanged.
76 77 78 79 80 81 |
# File 'lib/maquina_stream/block.rb', line 76 def seal self.class.new( index: index, markdown: markdown, html: html, line_range: line_range, sid: sid, sealed: true, digest: digest ) end |
#sealed? ⇒ Boolean
Whether this block is frozen — far enough behind the tail that nothing can reinterpret it, and therefore never re-broadcast.
56 |
# File 'lib/maquina_stream/block.rb', line 56 def sealed? = @sealed |
#to_manifest_entry ⇒ Object
[id, digest] — one row of a Manifest, and the unit the client diffs
its own DOM against.
85 |
# File 'lib/maquina_stream/block.rb', line 85 def to_manifest_entry = [id, digest] |