Understanding optionSplit Category: Typoscript A fresh look at the basics of the Typoscript optionSplit expression The TSref optionSplit entry serves well as an introduction to a powerful tool available to Typoscript. Despite its numerous examples to aid in clarifying the unfortunate terminology (What's the practical difference between a subpart and part? What does "the first part of the last value is repeated before the last value" mean?), it left me more curious than confident. I was ready to try some experiments of my own. My main goal was the find the boundaries of the optionSplit expression and to see if those boundaries helped in understanding the optionSplit rules. If possible, it would also be nice to have some sort of shorthand to represent patterns that can be rendered using optionSplit so that one could quickly and easily locate the expression need to render it. Let's quickly look at some terminology so we're talking about the same thing. An optionSplit expression is one-line string with a number of splitters or dividers organizing substrings into a hierarchy. We can call the full string the optionSplit expression or just the string. The TSref uses the terms "parts" and "subparts" to break this main expression down into relevant pieces. A "part" is a subexpression as determined by the location(s) of the |*| splitter. A "subpart" is a part that has been further broken down by the || splitter, and contains no further optionSplit operators. The TSref does well to demonstrate the purpose of optionSplit. In the simplest terms it is to provide a controlled structure for assigning attributes or values to a list of items (usually titles of pages for a menu) according to the number of items in the list. This is achieved with two types of dividers or splitters, which each split and prioritize the options according. The first divider is two horizontal lines: ||. It, according to the TSref, subdivides the first, middle and last into subparts and we'll call it the "subparts divider." This divider can, in reality, split more than three strings. The first, middle, and last parts are split using the second divider: |*|. This is the "parts divider," however, it might be easier to call it the "FML divider" (first, middle, last) since, as we shall see, this divider can only occur twice in an optionSplit expression, and therefore only splits the first, middle and last. The subparts divider, as previously mentioned, can occur any number of times in an expression, something that is not explicited said about these dividers. Clearly neither NEEDS to occur in any expression, as demonstrated by one of the first examples in the TSref: temp.topmenu.1.NO { backColor = red .... } There's no evidence of option-splitting occurring here, but all properties of .NO are parsed by optionSplit, and thus the second line is a valid optionSplit expression as it produces controlled output. Without either of the optionSplit dividers in the expression, the split output simply remains the same for each menu item. The shorthand I'm going to use in this article would represent this expression this way(note that the asterisk on the far right indicates repitition): n|*||*| produces n* Let's first look at how the parts splitter, aka the FML divider ( |*| ), behaves in simple expressions, and then follow with thesubparts divider ( || ) since its behavior varies with the context it appears in(ie whether it appears first, middle or last as determined by the FML divider). We are told that optionSplit prioritizes the options of this divider in the order: last, first, middle. first_part|*|middle_part|*|last_part This means that if there were only one menu page grabbed by the HMENU (we'll continue using the menu example as it is the most relevant), optionSplit would return: last_part. With two pages: first_part, last_part. With three or more pages the first_part would occur in the first slot, the last_part in the last and all middle pages would be middle_part since the middle repeats. Additionally, with no middle_part: first_part|*||*|last_part the first_part would simply repeat until the last_part terminates the optionSplit. This expression would be very useful for a menu where the items are separated by a horizonal line(often seen on footers of webpages), like this: Who | What | When | Where | Why | How Each page title has a horizonal bar following it, except for the last. We could describe this in a more useful shorthand like this: first..., second Since the last always has priority with the FML divider, and we have a repeating value for all other pages, this menu is created like this: lib.mainMenu = HMENU lib.mainMenu.1 = TMENU lib.mainMenu.1 { SPC=| expAll = 1 wrap = | NO.allWrap = | ||*||*| | NO.linkWrap= | } The | in the expression is the HTML character code for the horizonal line, spelled out so we don't interfere with stdWrap or optionSplit. Without the subparts divider in action, the rules for the FML divider can be summarized like this: 1. Priority is last, first, middle. 2. Middle will repeat as necessary. 3. If the middle value is empty, the first value will repeat until the last value. Since one of the goal listed above was to define the limits of optionSplit we could add this rule as well: 4. If the first and middle values are empty, the last value will repeat. Or, more generally: 5. If any two of the first, middle or last parts (remember, only as differentiated by the FML divider) are empty in an optionSplit statement, the place-value that is not empty will be repeated. As we know, however, we could just repeat by leaving all dividers out, so this rule is not going to be applied very often. The subparts divider ( || ) does not always behave the same way. Its behavior varies with the context in which it occurs. By context, in this case, we are referring to how the where in the expression it occurs in relation to the maximum of two FML dividers. In the first and middle part or context (with or without any FML dividers in the expression), the each value is activated in a first-come, first-served manner. This means that: first || second ||third || fourth with a 3-page menu will render: first, second, third. With a 5-page menu, however, the last value will repeat: first, second, third, fourth, fourth. In the same shorthand we used above we could describe this type of menu like this: x1||x2||x3...||xn produces x1,x2,x3,...xn* In the "last" context, like this: |*||*|first||second||third||fourth the tables turn, however. Suddenly we have a last-come, first-served situation where the first value repeats. What you see directly above with a 3-page menu will produce: second, third, fourth. With a 5-page menu we get: first, first, second, third, fourth. We'll describe this menu like this in shorthand: |*||*|x1||x2||x3||...xn produces x1*,x2,...xn Things only become slightly more complex when we have subexpressions in each of the three parts. The main rules still hold true: 1) the parts are prioritized last, first, middle, 2) the subparts are prioritized according to their context, 3) when there are enough values that a value needs to repeat, it comes from the lowest priority subpart, or 4) if there is a middle, it will rotate or repeat as necessary. These types of expressions would become increasingly difficult to describe in our shorthand. Here is an attempt to demonstrate how optionSplit would prioritize each item in a longer expression: 8 9 3 4 5 6 7 2 1 string1| |string2| |string3|* |string4| |string5|* |string6| |string7 The "middle" part will continue to cycle through its values until each item has a value assigned by optionSplit. Feel free to e-mail me if this article has or hasn't helped you in understanding optionSplit, or if there's something you'd like me to add.