This page looks best with JavaScript enabled

Gadget - Line numbers in modules

 ·  ☕ 3 min read

This week, we’ll take a look at a pretty straightforward gadget/user script & style snippet to add line numbers to Lua modules. As is often the case, despite its simplicity it’s one of the most helpful pieces of code I’ve written in terms of improving my day-to-day workflow.

(Note: All code in this post was originally written by me for Leaguepedia and is licensed under CC BY-SA 3.0.)

Motivation

If you use the CodeEditor extension, you get line numbers when editing modules, and of course if you use SublimeText you get line numbers when both editing and viewing modules (which is the same thing). But it’s also desirable sometimes to have line numbers just when viewing modules in the browser, particularly when checking traceback reports: CodeEditor is a smaller window than the full browser window (and isn’t dark mode!) so I prefer to view just a page rather than the editor. Line numbers are super needed, though, so I wrote a gadget to add them to the Module namespace. Let’s take a look!

Screenshot of a module with line numbers

(The SyntaxHighlight extension is also enabled here, using monokai from pygments-css.)

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* Add line numbers to modules */
$(function() {
	$('.ns-828 pre').each(function() {
		// Module:Teamnames on Leaguepedia is like 10,000 lines long. let's not do this there
		if (mw.config.get('wgTitle') == 'Teamnames') return;
		var lines = $(this).html().split('\n');
		$(this).html(
			lines
				.map(function(str) { return "<span class=\"pre-line\">" + str + "</span>" })
				.join('\n')
		);
	});
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.ns-828 pre {
  counter-reset:line;
}

.ns-828 pre .pre-line {
  counter-increment:line;
}

.ns-828 pre .pre-line::before {
  content:counter(line);
  text-align:right;
  position:absolute;
  left:-2em;
  display:inline-block;
  width:2em;
}

Explanation

JavaScript

As you can see from the comment, I need to manually exclude one page that this lags really badly on, Module:Teamnames. Other than that one page, this isn’t really a performance issue, but if you have any really long data modules or are using a slow laptop you may need to consider that.

All I do is take each pre element in the module namespace, split it on \n (newline), then wrap each individual line in a new <span> element with class .pre-line, and then join the thing back together. The rest is handled by CSS.

CSS

Really I just googled things like “CSS line numbers” and followed some tutorials, then added some extra styling to make them fit. I wrote this long enough ago that none of the results is still purple so I can’t tell you which articles I specifically read. The counter-reset, counter-increment, and content:counter rules are enough to add the numbers. The rest just positions them outside of the module at the start of the line.

For more information on counters, you can see:

Or just search for some blog post that goes more indepth into the CSS side than I do - CSS counters are really versatile!

If we weren’t using pseudoelements, which by default aren’t selected when a user highlights text, we might want to add some user-select:none; rule here, but being in a before takes care of this for us.

Conclusion

This gadget is pretty straightforward. It’s not the most performant thing ever and can degrade large pages significantly, but since I enabled it only for myself (really I just put it in my user JS, it’s not actually a gadget), I didn’t really care about that as an issue. The crux is just understanding how line numbering works in CSS and then writing a JS function to create the DOM elements needed to make it happen.

Share on

river
WRITTEN BY
River
River is a developer most at home in MediaWiki and known for building Leaguepedia. She likes cats.

What's on this Page