A text-rewriting pipeline is not just a collection of independent typography rules: each rule receives the text left by earlier rules, so changing their order can change the output. To be stable, the complete pipeline must reach a fixed point: running it again must leave the result unchanged. The article about polytypo describes nine rules in a defined order and uses examples to show why pipeline-level testing matters. Its project-specific details below are attributed to that article; they have not been independently verified here.
Why transformation order changes the result
Suppose a program runs transformations A, B, and C in sequence. B does not see the original input; it sees A’s output. C sees the result of both. A later transformation can therefore create a pattern that an earlier one would have changed—but that earlier transformation has already run for this pass.
As an Amazon Associate I earn from qualifying purchases.
The polytypo article describes its rule order as part of the project’s behavior, with spec/rules/order.json as the source of that order. It lists nine rules and their positions:
| Position | Rule | Qualification |
|---|---|---|
| 10 | spaces |
Listed in the article’s account of the project. |
| 20 | ellipsis |
Listed in the article’s account of the project. |
| 25 | ranges |
The article says this defined rule is off by default. |
| 30 | dashes |
Listed in the article’s account of the project. |
| 35 | hyphen |
Listed in the article’s account of the project. |
| 40 | quotes |
Listed in the article’s account of the project. |
| 50 | apostrophe |
Listed in the article’s account of the project. |
| 60 | symbols |
Listed in the article’s account of the project. |
| 70 | nbsp |
Listed in the article’s account of the project. |
These are project-specific rules, not a universal typography standard. The article says quote handling comes before apostrophe handling so a straight mark can remain available as quotation evidence; hyphen processing follows dash handling; and nonbreaking-space insertion comes last, after nearby punctuation has been resolved. It characterizes the rules as public API, making accidental dependence on registration or map-iteration order a compatibility risk. Because the article page was not available for direct inspection, treat this ordering and its rationale as the article’s account, not as independently confirmed current implementation behavior.
#1 Best Overall
Why testing each rule is not enough
A transformation is idempotent if applying it twice has the same effect as applying it once. For a complete pipeline transform, the condition is transform(transform(x)) == transform(x) for the inputs the system is expected to handle. Testing every rule on its own does not prove this condition for their composition: one rule may produce text that another changes in a way that matters when the sequence starts over.
The polytypo article gives .--. as an example of the problem. According to its excerpt, a pass promotes the hyphen pair to a spaced en dash, yielding . – .; on another full pass, a spacing rule removes the space before the full stop, producing . –.. This is an example reported by the article, not a reproduced test. It illustrates how a later rule’s output can become work for an earlier rule on the next pass.
A useful composition principle follows: a rule may create text for a later rule that has not run yet, because that later rule can still process it in the same pass. But if the output creates a pattern that an earlier rule would have changed, the pipeline may need a second pass. Avoiding that outcome requires considering the complete sequence, not merely checking that each rule behaves consistently in isolation.
Recommended Free Tools
Where a problematic pattern should be fixed
The article also describes a French-guillemets case. Straight double quotes around a bare hyphen are converted to guillemets with no-break spaces; a later dash rule may then mistake the flanked hyphen for a parenthetical dash on a subsequent pass. The article argues that the fix belongs in dash recognition, not in no-break-space insertion.
That is a rule-ownership question: which transformation has enough context to distinguish the intended punctuation? If dash recognition is responsible for classifying dashes, correcting its recognition logic keeps the decision with the rule that owns it, rather than changing spacing behavior to compensate. This example, too, is the article’s description and has not been independently checked against the implementation.
What “spans” and markup do—and do not—establish
The article title refers to spans, but its accessible excerpt does not establish polytypo’s span representation or edit-boundary algorithm. It does not support conclusions about offsets, interval conventions, overlapping edits, or how boundaries are discarded. Those implementation details should not be inferred from browser standards.
Rank #4
CSS has its own rules for text processing across markup. CSS Text Level 4 says inline box boundaries and out-of-flow elements are ignored when determining adjacency for many text-processing operations, while directing readers to a separate rule for shaping across element boundaries. That describes browser processing, not the internal representation of a string-rewriting library: W3C CSS Text Module Level 4.
A library rewrite is different from browser text layout
Browser text processing is a rendering and layout sequence, not necessarily a mutation of the stored text. CSS Text Level 3 lists operations including whitespace processing, text transformation, line wrapping, bidirectional reordering, glyph selection and positioning, spacing, justification, and alignment. It says, “Implementations are not bound to this order as long as the resulting layout is the same.” That flexibility concerns equivalent rendered layout; it is not a reason to treat a text library’s explicitly ordered mutation rules as interchangeable. See CSS Text Level 3, Appendix A: Text Processing Order of Operations.
CSS text-transform changes presentation rather than the underlying content: CSS Text Level 4 says it does not alter the content and plain-text copying, and warns against relying on it for semantics. If punctuation or spacing must be changed in stored text, that is a different task from asking the browser to render text differently. See CSS Text Level 4: Text Transformation.
Quick Recap
How to evaluate a text-rewriting pipeline
- Make the sequence explicit. If order affects output, keep the order in a deliberate, reviewable definition rather than relying on incidental registration or iteration behavior.
- Test the composition. Run the complete pipeline twice on representative inputs and check whether the second result changes. Individual-rule tests cannot establish whole-pipeline idempotency.
- Check interactions around punctuation. Include cases where one rule changes a character or its neighbors and another rule classifies that result.
- Keep browser behavior separate. CSS layout standards explain rendered text behavior, not the edit mechanics of a library that rewrites source content.
- Do not infer span mechanics from a title. Confirm the implementation’s boundary and overlap behavior before relying on it.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




