Compatibilizando puertadeenlace.net

Quienes hayan entrado en la última semana a www.puertadeenlace.net utilizando Iimagenternet Explorer 8, habrán notado un pequeño ícono al lado de la barra de herramientas (ver imagen). Este ícono nos muestra que el sitio no es compatible con IE8, dado que no cumple con estándares definidos por la W3C. En este post iré plasmando el trabajo a realizar para que esto no ocurra, y que nuestros sitios sean compatibles con los estándares definidos, y puedan ser navegados por todos los browsers.

Primer paso: Identificando errores

Presionando F12 en IE8, accedemos a la barra de herramientas para desarrolladores de IE8 (escribí sobre esto hace un tiempo). Allí seleccionamos la opción Validate –> HTML del menú.

image

Allí accedemos al validador de la W3c, donde se nos inidica los errores, advertencias, y cuales son las causas. En mi caso son 18 errores y 3 warnings.

image

Segundo Paso: Corrigiendo errores

En el caso de puertadeenlace.net estamos usando un engine de blogging Open Source llamado BlogEngine.NET. BlogEngine.NET está desarrollado enteramente en ASP.NET, y la publicación del sitio es no compilada. BlogEngine.NET además ofrece Widgets y Extensiones que complementan y alteran al engine principal de blogging.

Para corregir los errores estaré modificando el código del sitio, que mantiene referencias al engine principal de BlogEngine:

Primer error: No hay un atributo “name”

Error Line 8, Column 15: there is no attribute "name".

     <form name= " aspnetForm" method="post" action="/Default.aspx" id="aspnetFor…

You have used the attribute named above in your document, but the document type you are using does not support that attribute for this element. This error is often caused by incorrect use of the "Strict" document type with a document that uses frames (e.g. you must use the "Transitional" document type to get the "target" attribute) , or by using vendor proprietary extensions such as "marginheight" (this is usually fixed by using CSS to achieve the desired effect instead).

This error may also result if the element itself is not supported in the document type you are using, as an undefined element will have no supported attributes; in this case, see the element-undefined error message for further information.

Si bien no estamos usando frames, ASP.NET siempre agrega un nombre al formulario para la correcta identificación de los parámetros. Por ello en este caso vamos a optar por modificar la firma del DocType utilizando el tipo Transitional tal cual fué recomendado:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Refresh al validador: Validation Output: 15 Errors, 3 Warnings

Segundo error: El elemento h1 no es permitido en esa ubicación

Error Line 21, Column 33: document type does not allow element "h1" here; missing one of "object", "applet", "map", "iframe", "button", "ins", "del" start-tag.

                      <h1 id="logo" >  

The mentioned element is not allowed to appear in the context in which you've placed it; the other mentioned elements are the only ones that are both allowed there and can contain the element mentioned. This might mean that you need a containing element, or possibly that you've forgotten to close a previous element.

One possible cause for this message is that you have attempted to put a block-level element (such as "<p>" or "<table>") inside an inline element (such as "<a>", "<span>", or "<font>").

Podemos notar que el mismo error es identificado por Visual Studio:

image

Como vemos, un tag h1 no puede estar anidado en un tag a, con lo cual invertimos el orden.

Refresh al validador: Validation Output: 14 Errors, 3 Warnings

Tercer error: Entities no definidos

Error Line 174, Column 103: general entity "i..." not defined and no default entity.

  …e;o del mismo. Incluso desde el mism&i... <a href="/post/armando-el-briefing. 

This is usually a cascading error caused by a an undefined entity reference or use of an unencoded ampersand (&) in an URL or body text. See the previous message for further details.

BlogEngine.NET crea un resumen de cada post tomando los primeros N caracteres del mismo. Aparentemente no está considerando la existencia de entities codificados, con lo cual estamos viendo un bug de BlogEngine.NET. Para corregirlo, voy a modificar la clase PostViewBase de BlogEngine.Core, para desencodear el texto antes de acortarlo, y luego volver a acortarlo (puede que esta no sea la solución más elegante u optima, pero prefiero modificar al minimo código ajeno):

body = Utils.StripHtml(Post.Content);

body = Server.HtmlDecode(body);
if (body.Length > 300)

    body = Server.HtmlEncode( body.Substring(0, 300) ) + "..." + link;

Compilamos y actualizamos la biblioteca referenciada en el sitio web. Reporté el bug para que puedan corregirlo en el trunk del proyecto.

Refresh al validador: Validation Output: 12 Errors, 2 Warnings

Cuarto error: Comillas no encodeadas

Error Line 186, Column 65: "MSDN" is not a member of a group specified for any attribute.

 …ef="mailto:?subject=Armando el "MSDN y TechNet Briefing"&amp;body=Thought you

Al armar el link para el envio de mail, el theme que estamos usando está olvidando encodear a entities el título del post, con lo cual el link resulta roto. Para ello modificaré el código para que lo haga:

…mailto:?subject=<%=Server.HtmlEncode( Post.Title ) %>&amp;body=…

Refresh al validador: Validation Output: 1 Errors, 1 Warning!!!

Quinto error: Otros símbolos no encodeados

Warning Line 61, Column 4314: character "&amp;" is the first character of a delimiter but occurred as data.

 …nlace.net) online">Novedades de MSDN  &  Tec...</a></li><li><a href="https://egl

This message may appear in several cases:

  • You tried to include the "<" character in your page: you should escape it as "&lt;"
  • You used an unescaped ampersand "&": this may be valid in some contexts, but it is recommended to use "&amp;", which is always safe.

Ya voy notando que el theme que estoy usando ignora en más de un lugar el encodeo de entidades, lo cual genera problemas. En este caso se trata del widget “BlogRoll”:

image

 

El error está en el control BlogRoll, al transformar en HTML el contenido extraido de los feeds registrados:

  private void AddRssChildItems(RssItem item, HtmlGenericControl li)

    {

      if (item.ItemTitles.Count > 0 && BlogSettings.Instance.BlogrollVisiblePosts > 0)

      {

        HtmlGenericControl div = new HtmlGenericControl("ul");

                for (int i = 0; i < item.ItemTitles.Count; i++)

                {

                    if (i >= BlogSettings.Instance.BlogrollVisiblePosts) break;

                    HtmlGenericControl subLi = new HtmlGenericControl("li");

                    HtmlAnchor a = new HtmlAnchor();

                    a.HRef = item.ItemLinks[i];

                    a.Title = HttpUtility.HtmlEncode(item.ItemTitles[i]);

                    a.InnerHtml = HttpUtility.HtmlEncode(EnsureLength(item.ItemTitles[i]));

                    subLi.Controls.Add(a);

                    div.Controls.Add(subLi);

                }

        li.Controls.Add(div);

      }

    }

Refresh al validador: Passed!!!

Conclusiones

Tal vez sean pocos los que estén usando el mismo Engine, pero el propósito del post es mostrar un procedimiento a seguir a la hora de eliminar los errores de validaciones HTML.

Vemos cómo ignorar el encodeo de entidades podría generar problemas en el parser que utilice un browser, resultando en un error de visualización a los usuarios.

Por otro lado IE8 facilita el descubrimiento de estos errores. www.puertadeenlace.net es ahora 100% compatible.

Valid XHTML 1.0 Transitional

Ahora a corregir los 94 warnings del CSS :)

Miguel.