The HTML/CSS woes in Luminous holding up 0.7 development.

Published September 21, 2012

Luminous 0.7 uses the brilliant (I thought) idea of using CSS counters and ::before pseudo-elements to add line-numbering to HTML output for Luminous, which cleaned and cut back the markup considerably. Unfortunately, as is often the way when you do something clever, there are some unforeseen problems, which are now holding up the process, and a satisfactory solution to all requirements is not obvious.

1) Clean code

Luminous 0.6 uses a table with one row and two cells - line numbers in the left cell, code in the right. HTML fascists (no offence, I'm one too) will scream at the thought of using a table for layout, but simply put, it works, and this is more than can be said for most alternatives. Let's be clear here: tables were used for layout originally because HTML didn't provide good means of doing common things, and we're using tables again because HTML doesn't provide good means of doing less common things. GitHub's brand of Pygments works in the same way, as does BitBucket's (I'm pretty sure Pygments doesn't do line numbering by default, so these have been added by the respective sites). CodeRay works in the same way. So it's not just Luminous. SyntaxHighlighter works with ordered lists but, even if you didn't know this already, it's plain from SH's output that lists are hard to style.

But I agree, tables are awful semantically, and I want nothing more than to move away from this layout. It's also problem prone in the sense people are likely to apply a blanket site-wide styling to tables, which is likely to interfere with the syntax highlighter's CSS.

The pseudo-elements + counters would work wonders if it could satisfy all the other requirements.

2) Copy and paste

It's a basic, although easily forgotten, requirement that copying code from your browser to your text editor should leave the code intact. Chrome is extremely happy with a set of spans (lines) inside a pre. Firefox, however, is not. Firefox strips all whitespace, i.e. linebreaks and indents. Not so good if you're writing Python. I really don't know why this is - the spans are inside a pre and they display correctly, and I'm sure copy and paste in Firefox normally works properly with pres. So it seems to be an edge case (sidenote: FF has a 10 year old unclosed bug for the same problem copying and pasting from 'white-space: pre;' styled elements).

Changing the spans to a list, using li for each line, fixed the line-breaks, but the indents are still broken. And having an ol inside a pre is invalid anyway.

Furthermore, Internet Explorer and Opera have issues with the pseudo-elements - they include them in the copy and paste. I don't really care about IE, but if Opera is doing it too ... there's nothing in the w3c spec about copying and pasting, so it's implementation dependent - does that mean we can really rely on Chrome and Firefox to continue working the way they do? Including line numbers in the copy and paste is disastrous.

3) Validation

Validation is one of those things - it's kind of academic; who cares as long as browsers display it correctly, right? But on the other hand, you're in undefined territory, so ignoring the spec is at your peril.

4) Scrolling

The holy grail is to make Luminous widgets function like a standard programming text editor in terms of scrolling - that means the vertical scroll scrolls both code and line numbers, but the horizontal scrolling scrolls only the code panel and leaves line numbers fixed on the left. This just doesn't seem possible. Even with the old table layout.

Failing that, we just want it to be relatively easy to browse arbitrarily sized (number of lines and line widths) code without breaking containers when something big is given.

In conclusion, it's getting there but unfortunately the markup and CSS is still unstable as far as development goes. In better news, 0.7 now has a fully working SCSS scanner.

It's an incredible reflection on HTML that the most troublesome part of a huge syntax highlighting library is figuring out how to arrange 3-4 HTML elements in the right way.