Styling LMNL

From LMNLWiki

This page holds some initial thoughts about how LMNL might be styled using a language similar to CSS.

Contents

Selectors

The syntax of CSS Selectors, even in CSS3 which at least supports namespaces, doesn't support the LMNL model very well. In particular:

  • CSS selectors can't handle structured and annotated annotations very well.
  • CSS combinators understandably focus on parent/child/descendant/sibling relationships, whereas the relationships between ranges in LMNL are a lot more complex

It could also be said that the evolutionary path that CSS has taken has meant that its syntax is a little peculiar. For example, using | as the prefix/local-part separator in a qualified name, rather than the usual :, is not ideal for those familiar with XML.

Further, it would be fantastic if we could unify selectors used in a CSS-like styling language with patterns used in a XSLT-like transformation language. They do have different aims (in particular, a styling language benefits from pseudo-elements and pseudo-classes whereas a transformation language probably doesn't, and it's probably more important for selectors in a styling language to be streamable), but similar syntaxes would make both languages more accessible.

Styling Overlap

The biggest issue with styling LMNL using a CSS-like language is how to deal with overlap. The properties in CSS can be roughly divided into two groups: those to do with fonts and those to do with layout.

Fonts

Any font properties, such as the typeface, font size, variant, weight, colour and so on, should apply to all the text within a range. When another range starts, most properties are inherited from the previous range, unless a new value is specified. When the range ends, those properties revert back to what they were.

For example, given the LMNL

[red}this is red [blue}this is blue{red] and this is blue{blue]

and the CSS stylesheet

red  { color: red; }
blue { color: blue; }

the text within the [red] range should be red, and that within the [blue] range should be blue. The text within the overlap is also blue, because when the new [blue] range starts, the color property is set to the new colour.

Layout

What about if the CSS stylesheet said

red { border: thin solid red; }
blue { border: thin solid blue; }

For borders, margins and so on, we probably want the boxes to actually overlap, so the text within the [red] range was surrounded with a red border and the text within the [blue] range was surrounded with a blue border:

this is red this is blue and this is blue

In this example, both the red and blue borders are present around the text that appears in both ranges, but because the blue border is drawn second, it obscures the red border. If the two boxes had different padding then both boxes would be visible.

This can be mocked up programmatically by wrapping adjacent characters into a <span> element for each range in which it's contained. If the text falls at the start of the range, then the left margin/border/padding gets applied to the span; if it falls at the end of the range, then the right margin/border/padding gets applied to the span, and either way the top and bottom apply. For the example above, the code is:

<span style="border-left: thin solid red; 
              border-top: thin solid red; 
              border-bottom: thin solid red; 
              border-right: none">this is red </span>
 <span style="border-left: none; 
              border-top: thin solid red; 
              border-bottom: thin solid red; 
              border-right: thin solid red;">
   <span style="border-left: thin solid blue; 
                border-top: thin solid blue; 
                border-bottom: thin solid blue; 
                border-right: none;">this is blue</span>
 </span>
 <span style="border-left: none; 
              border-top: thin solid blue; 
              border-bottom: thin solid blue; 
              border-right: thin solid blue;"> and this is blue</span>