Documentation
¶
Overview ¶
Command tee streams a document to two destinations at once - one rewritten, one exactly as it arrived - from a single read of the input, and reports how far apart they ran.
$ tee -rewritten out.html -verbatim raw.html page.html 7400 bytes in, 10400 out rewritten, 7400 out verbatim widest gap 12 bytes, with the verbatim copy ahead held by a start tag no selector had ruled out sink calls 4400 rewritten, 200 verbatim
The verbatim copy is the input, so there is nothing to compute for it: tee the reader and give one branch to the rewriter. What is worth knowing is the gap, because it is the only view from outside of what the rewriter is holding.
A start tag is held until every selector has been ruled out ¶
The verbatim copy runs ahead by whatever the rewriter has buffered, and that is bounded by one start tag rather than by the document. Which tag depends on the selectors, and not on whether any handler ran. Feeding a 5513-byte document one byte at a time and watching the widest gap:
document selector widest gap
<div data-x="1" … >x</div> none 5
a[href] 5
span[data-x] 5
div[data-x] 5505
div[data-absent] 5505
div.absent 5505
div#absent 5505
[data-absent] 5505
* 5505
A tag name rules a selector out at the name and the rest of the tag streams. An attribute, a class or an id cannot be ruled out until the tag ends, so the tag is held whether it matches or not - div[data-absent] holds as much as div[data-x] does. A selector with no tag-name component holds every tag.
So the bound is the longest start tag whose name some selector does not exclude. Ordinary markup gives a gap of a few bytes; a tag with five hundred attributes gives five thousand, and only if a selector could still be interested in it. Text is never held: a 10 KB text node ran a gap of three bytes with a text handler registered and without one.
The one way to make the gap the size of the document is to do it yourself - accumulating a text node to lolhtml.TextChunk.IsLastInTextNode and removing the chunks along the way held 10003 of 10007 bytes. That is the caller's buffer, not the rewriter's, and it is worth knowing which is which when a memory figure looks wrong.
The two destinations fail differently ¶
The verbatim copy is written first, so a rewrite that fails has already put bytes in it. There is no ordering that avoids this: whichever is written first is ahead when the other breaks. What a caller can do is know which, and this reports the counts so a partial pair is recognisable rather than surprising.