Weblog

Cómo añadir números de linea a los bloques de código

Acabo de descubrir cómo añadir números de linea a los bloques de código que están dentro de texto preformateado. Se trata de usar una función javascript que recoge todos los elementos pre, y llama a una expresión regular que devuelve el número de lineas en ese bloque. Entonces, usando innerHTML simplemente añadimos una capa div que contiene los números de linea y se le da estilo usando CSS. El javascript, que forma parte de un espacio propio (un objeto literal para encapsular sus funciones) sería algo del estilo:


// 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;
	}
},

El CSS podría ser algo parecido a estas lineas:


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;
	}

La técnica parece funcionar solamente en Mozilla y Opera. IE reemplazaba los saltos de linea por espacios así que lo he ignorado. Los demás navegadores degradan tranquilamente.

Como ya han comentado, en Mozilla hay un fallo que no permite la selección de bloques de código que están dentro de bloques de texto preformateado. He intentado añadir un fondo de color (solamente para Mozilla) al pasar el ratón por encima, porque así parece un poco más fácil de ver cómo poder seleccionar. Aparentemente, si empezamos la selección en el espacio que hay entre el texto preformateado y el bloque de código (el espacio en blanco entre los números y el código), se deja seleccionar.

Comentarios sobre esta entrada

  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.

Cerrado

Debido a la mierda de spam este weblog queda cerrado a comentarios, era imposible mantener el script de la lista negra al día. Si quieres busca mi email y enviame un mensaje. Lo siento.

Cambia las preferencias

Cambia las preferencias

Licencia

Creative Commons 2001-2004. Sergi Meseguer

Sindicación RSS

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