Weblog

How to add line numbers to code blocks

I've just discovered how to add line numbers to code blocks inside preformatted text. I've used a javascript function that loops through all pre elements, and calls a regular expression that returns the number of lines in that block. Then, using innerHTML i just add a div containing the line numbers and style it using CSS. The javascript, that is part of a namespace (an object literal to provide encapsulation) is something like this:


// adds line numbers to code sections:
numberCodeTags : function(){
	var PRE = document.getElementsByTagName('pre'); 
	var nl = /\n+/mg;
	for (var i = 0; i < PRE.length; i++) {
		var t = PRE[i].innerHTML;
//mozilla/ff cannot select all lines of a code element 
//that is inside a pre element:
		if(document.addEventListener && !window.opera) {
			Extras.getCodeText(PRE[i]);
		}
			
//will only work in mozilla+op (IE replaces \n by a space so its useless):
		var NL = Extras.getMatchArray(t,nl);
		if(NL) {
		var numeros = "";
		for (var lineas = 1; lineas < NL; lineas++) 
		numeros += lineas +"\n";
		PRE[i].innerHTML += "<div class='lines'>"+numeros+"</div>";
		}
	}
},
	
// matches a regexp to a string, returns array
getMatchArray : function(myString,myRegExp){
	return myString.match(myRegExp).length;
},

// FF  hack to make easier select all lines of a 
//code element that is inside a pre element:
getCodeText : function(obj){
	var color = CSS.getStyle(obj.firstChild,"color");
	var bgcolor = CSS.getStyle(obj.firstChild,"backgroundColor");
	if(bgcolor=="transparent") bgcolor="white";
	obj.onmouseover = function(){
		obj.firstChild.style.color = bgcolor;
		obj.firstChild.style.backgroundColor = color;
	}
	obj.onmouseout = function(){
		obj.firstChild.style.color = color;
		obj.firstChild.style.backgroundColor = bgcolor;
	}
},

CSS could be something similar to the following lines:


pre	{
	position:		relative;
	color: 			#913117;
	padding: 		0px 1em 0px 1em;
	margin: 		0px;
	font-family:		Courier, monospace; 
	font-size:		1em;
	}
code	{
	font-variant: 		normal;
	color: #913117;
	}
pre code	{
	position:		relative;
	top:			0px;
	left:			1.2em;
	font-variant: 		normal;
	color: 			#913117;
	padding: 		0px;
	margin: 		0px;
		}
pre .lines	{
	position:		absolute;
	top:			1em;
	left:			0px;
	width:			1.2em;
	padding: 		0px;
	margin: 		0px 1.2em 0px 0px;
  	background: 		#913117;
	color: 			white;
	}

This technique seems to work in Mozilla and Opera only. IE replaces line feeds with spaces, so I simply ignored it. All other browsers degrade.

As stated in forst comment, Mozilla has a bug that doesnt let you select a block of code that is inside a preformated text. I tried to add a background color (only in Mozilla) onmouseover, this way block size is better seen. Apparently, if we start selection inside the free space outside the code block (the white space between numbers and code) you can select the code easily.

Comments on this entry

  1. 2004-11-30 02:00:55

    en firefox funciona bien ;-) pero ahora no me deja seleccionar más de una línea, e incluso si me dejara seleccionarlo todo, me incluiría dichos números de línea, lo que no deja de ser un engorro :-(
  2. 2004-11-30 05:48:39

    El problema no es del script, es de Mozilla/FF para seleccionar bloques de código que están dentro de bloques de texto preformateado. Si desactivas el javascript verás que tampoco puedes seleccionar másde una linea. Estoy en ello.

    De todos modos, como apaño rápido puedes seleccionar una palabra y clickar con el botón derecho para hacer un View Selection Source. Eso abre una ventana con el texto pegado. El problema es que al tratarse de código que ha tenido que estar pasado a entidades (ejemplo & lt ; en lugar de <), al pegarlo en la ventana se ven las entidades, no el resultado visual.

    por cierto, cuanto tiempo sin verte! ;)

  3. 2004-11-30 10:07:39

    es verdad, acabo de comprobar el problema de Mozilla/FF, aunque el apaño va del diez ;-) // creo que te confundes de sergio, yo llevo poquito tiempo por aquí
  4. 2004-11-30 12:15:49

    Pues parece que el problema no es de Mozilla, es de mi CSS, que debe hacerle algo raro impidiendo que seleccione más de una linea. El truco de empezar desde fuera de la etiqueta code es un apaño guarrete...

  5. 2004-12-01 06:48:33

    es el position:relative el que vuelve loco a Mozilla...
  6. 2004-12-01 07:52:55

    que bien me viene estooo. A ver si tengo un ratín e intento implementarlo en el blog. Lo que me encantaría es poder colorear también el código, pero supongo q eso ya se me sale del presupuesto (mental). Great.
  7. 2004-12-02 16:20:48

    Jesus: puede que te interese Geshi (también incluye números de línea). Eso sí, es todo php :P
  8. 2004-12-09 11:02:31

    ey, muchas gracias mur. no había visto el mensaje hasta ahora (que he vuelto para apoderarme del script de los números de línea).
  9. 2005-05-04 13:49:37

    • Silvestre
    • [e]
    perdona, pero quisiera consultarte una cosa respecto al innerHtml. aqui lo has usado para insertar etc... el problema que tengo yo es que lo he usado para insertar dentro de un documento html, una variable de javascript. funciona en MIEx, pero en Mozilla no me funciona. bueno si que me funciona pero en mozilla solo pasa cadenas de texto y no admite variables. gracias y perdona por entrar en este blog. no se donde podria realizarte esta pregunta.

Closed

Due to spam bullshit this weblog has been closed to comments, it was impossible to keep my blacklist script updated. You can still figure out my email and send me your message. Sorry.

Change preferences

Change preferences

License

Creative Commons 2001-2004. Sergi Meseguer

RSS syndication

rss (1, 2 ), xhtml, css, taw