Lists are a powerful way to making complex ideas easier to digest, better than caramel. Auditorily I defined them via a thunk earcon, with or without the insertion of tiered numbering. Visually they’re denoted by preceding each list item by a symbol (•) or number.
These numbers are commonly rendered using one of a variety of counting styles, including:
And that’s without getting into non-latinate languages!
To let webdevs configure how counters are rendered, the W3C are standardising the
@counter-style at-rule. I’ve implemented this in Haskell Stylist to make implementing all the standard (and more) counter-styles trivial!
These counter-styles defines:
But most importantly it includes a “counting system” & the Unicode characters/symbols with which it should be used.
These counting systems may be one of:
cyclicwhich repeats a given sequence of symbols as the markers.
fixedwhich iterates over a given sequence before falling back, where the number associated to the first symbol is configurable.
symbolicwhich doubles (then triples, etc) up the symbols once we’ve iterated through them.
alphabeticwhich works similarly to
numeric, but tweaked to work better with alphabetical symbols.
numericwhich repeatedly divides by some base & outputs corresponding symbols for the remainders.
additivewhich iterates over symbol/value pairs to greedily output a sequence with the desired sum. Think Roman Numerals where X = 10, V = 5, & I = 1.
These collectively can be configured to describe almost all the numbering systems used around the globe.
The Western numbering system (which is derived from India’s via Arabia) isn’t the only numbering system. Most can be handled by the
numeric system, or the flexibility of the
additive system. There’s plenty of alphabets to use with the
alphabetic system, & the other systems have their uses.
The W3C provides a sample stylesheet which I copied & pasted into my codebase. They say they don’t expect “useragents” (their term for webbrowsers) to implement all of these, but I did anyways since it was trivial & to show a commitment to internationalization.
Except there’s a few numbering systems known to the W3C which needed to be implemented specially!
Chinese has 4 numbering systems which, with some nuances, favours denoting the 1s, 10s, 100s, & 1000s places as opposed addings zeroes (
零). These systems differ in which logograms are used & whether shorthands are used for the teens. This was implemented with a little postprocessing after converting the number to decimal digits. Several Chinese numbering systems can be implemented as variants on this generic algorithm.
Ethiopian numerals (historically used across northern Africa) meanwhile, with it’s own nuances, pairs up every 2 digits. Between each pair it intersperses alternating
፼ seperators. Within each pair, the tens place uses different characters from the one’s place. For zero & negative numbers, as per W3C’s recommendation, I fallback to the Western numbering system.
I minorly extended the
@counter-style spec with a couple extra
systems for internal use to invoke these algorithms with (partially, in the case of Ethiopian) configurable Unicode symbols. Webdevs are discouraged from taking advantage of this & should instead use the browser-independant:
I took testcases out of that W3C spec to ensure I got all this correct.
I refactored how I’m exposing pseudoelements, now I’m exposing them to
PropertyParser implementations as opposed to the library’s caller. This necessitated an addition to the “Stylist Traits” hackage, which I introduced to minimize the transitive dependencies in other components of the Argonaut Stack including Stylist compatibility. This will likely be useful again the future!
This change allowed the
Data.CSS.Preprocessor.Text styletree-preprocessor to handle inserting the
::after, & for list items (declared via
::marker pseudoelements. The
::marker pseudoelement holds the list item’s bullet or counter, who’s contents (if absent) is generated from
list-style-image (relies on as-yet unimplemented image content) or
list-style-position: outside I lower the list item to (as-yet unimplemented) flexbox & generate a new styletree element around it’s other children (including
::after) so the marker can lie outside. Whether the marker is at the start or end depends on the
direction CSS properties.
These list items automatically increment a
list-item counter, determining which number is rendered via the specified counter-style.
P.S. I proofread this preprocessor, leading to the discovery of several bugs to squash. Nothing I find worth explaining in detail.
Several CSS shorthands, like
list-style, allows you to specify subproperty values in any order. A utility in Stylist Traits was added to aid implementing these.
It splits out function arguments, before associating each token with the first matching subproperty. Then iterates to the next token/function to match against remaining subproperties. Any leftover subproperties are set to