Documentation
¶
Overview ¶
Command split cuts a document into parts at a chosen heading level, and makes each part stand on its own.
$ split -level 2 -o out < book.html 3 parts, cut at <h2> out/part-1.html 1284 bytes "Introduction" reopened <html><body><article> out/part-2.html 4218 bytes "The middle part" reopened <html><body><article> out/part-3.html 902 bytes "Afterwards" reopened <html><body><article>
One rewriter, several destinations ¶
A rewriter writes to one destination, and a split needs several - so the destination is a writer that forwards to whichever part is current, and the handler that meets a heading tells it to move on. The rewriter never knows: from its side this is one document, which is what keeps the parse and the offsets right.
What makes a part stand on its own ¶
The tags that were open when the cut happened. A heading three levels inside <html><body><article> starts a part whose text is inside nothing at all unless those three are written again - so each part begins with the ancestors' start tags, as they appeared in the source, and ends with their end tags in reverse.
The rewriter is what makes that possible: an element handler knows the tag and its attributes, and its end-tag handler is where the ancestor leaves the stack. No tree, and no second pass - but the end-tag handler is not enough on its own. HTML lets a document omit </p>, </li> and </td>, and an element closed that way is reported at the token that closed it, which belongs to an ancestor and arrives long after the element ended, or never arrives at all. A stack driven by end tags alone therefore keeps ancestors that have already finished, and every later part reopens them: <article><p>intro<h2>One reopens <article><p>, then <article><p><p>, and each part closes tags it never opened. So the stack also pops on a start tag, following the specification's implied end tags - impliedlyClosedBy below is that table, and it is the same one examples/gip/depth needs for the same reason.
The reopened tags are the source's own, attributes included, because a part whose <article> has lost its class is a part that styles differently. What is not reproduced is anything the ancestors' *content* said before the cut - a part does not get the previous part's paragraphs - which is the point of cutting.
Where a cut is allowed ¶
At a heading of the chosen level, and nowhere else. A byte budget with -max moves the cut to the next heading after the budget is exceeded rather than cutting mid-element: a part that is larger than asked for is a nuisance, and a part that ends inside a tag is not a part.
The budget is counted at the destination rather than at the input, because the output is what a caller is sizing - and the two differ whenever a handler edits anything.