Introducción ************ .. _html-url: Hiperenlaces ============ Ya se ha dejado establecido que lo que convierte al *hipertexto* en *hipertexto* son los *hipervínculos*. Relacionados con ellos, existen tres conceptos muy recurrentes: |URI| En castellano :dfn:`Identificador Uniforme de Recurso`, es un identificador que permite declarar inequívocamente en internet cualquier recurso. Por lo tanto, cada recurso debe tener uno y que sea único. Ahora bien, hay dos modos de identificar un recurso: por su nombre o por su ubicación. Estos dos son los conceptos que se presentan a continuación. |URN| En castellano, :dfn:`Nombre Uniforme de Recurso`, es un nombre único que identifica a un recurso inequívocamente en internet. |URL| En castellano, :dfn:`Localizador Uniforme de Recurso`, es la ubicación en la que se encuentra el recurso. Como en el caso anterior, forzosamente es única. Por hacer un símil. Si hablásemos de personas, en vez de recursos, la |URN| sería su nombre y la |URL| la dirección de su domicilio. Ahora bien, si intentamos identificar a una persona por su nombre, no podremos si existen dos personas con idéntico nombre; y, si por su domicilio, tampoco si en una misma casa viven varias. En el caso de los recursos, esto no sucede, porque nombre y ubicación deben ser únicos. Un ejemplo real de |URL| y |URN| se halla en la :ref:`definición del tipo de documento ` cuando son dialectos |XML| estandarizados y públicos: .. code-block:: dtd En esta definición para |XHTML| **1.0**, hay una |URN|: .. code-block:: none -//W3C//DTD XHTML 1.0 Strict//EN y una |URL|: .. code-block:: none http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd Esta última es la ubicación del |DTD| que define la gramática del dialecto. Formato ------- Dado que la base del *hipertexto* es el *hipervínculo*, que debe llevarnos a la ubicación de otro *hipertexto*, es previsible que en la redacción de un |HTML| requiramos escribir |URL|\ s, por lo que es muy importante saber cuál es su formato exacto. En principio, podemos definir este formato del siguiente modo esquemático: .. code-block:: none esquema://maquina/ruta que puesta en ejemplo concreto es: .. code-block:: none http://docs.iescdl.es/~josem/XML/07.html/01.intro.html Las partes constituyentes son: **esquema** (``http``) Identifica el tipo de recurso, por lo general, el protocolo de servicio por el que se accede a ellos. Por ejemplo: * ``http`` para páginas web. * ``https`` para páginas web en que la conexión es cifrada. * ``ftp`` para ficheros a los que se accede por |FTP| **maquina** (``docs.iescdl.es``) Es el nombre de la máquina (o la dirección |IP|) en la que se encuentra el recurso. Ahora bien, su expresión puede ser un poco más complicada para admitir más información: .. code-block:: none [usuario[@contraseña]:]maquina[:puerto] Si el recurso está protegido, puede añadirse antes del nombre de la máquina un usuario y su contraseña. Si se accede a la máquina a través de un puerto no estándar, entonces es también posible añadir cuál es ese puerto. **ruta** (``/~josem/XML/07.html/01.intro.html``) Es la ruta del recurso dentro de la propia máquina. Cuál sea esta ruta dentro del propio sistema de ficheros de la máquina, depende de la configuración del servidor web, pero se comporta de manera semejante a como lo hacen las :ref:`rutas en los sistemas UNIX `. Trataremos esto bajo el próximo epígrafe. .. note:: Incluso en los ejemplos en los que, aparentemente, no hay ruta, sí la hay. Por ejemplo, ante esta petición sin, aparentemente, ruta: .. code-block:: none http://www.example.com el servidor web añada una ruta que depende de cómo se haya configurado. Habitualmente, :file:`/index.html` o :file:`/index.php`. .. _html-abs-rel: Rutas absolutas y relativas --------------------------- Del mismo modo que las rutas de un sistema de ficheros, las |URL|\ s pueden ser: **absolutas** Son aquellas que expresan la ubicación indicando toda la información: esquema, máquina y ruta. Las rutas indicadas bajo el epígrafe anterior son rutas absolutas: Un concepto importante que es necesario introducir es el de .. code-block:: none http://docs.iescdl.es/~josem/XML/07.html/ **relativas** Son aquellas que expresan una ubicación tomando una referencia y, en consecuencia, no necesitan especificar todos sus componentes (esquema, máquina, etc.), ya que algunos, gracias a la referencia, se sobreentienden. Para proseguir es necesario explicar cuál es esta referencia: la :dfn:`URL base` es la |URL| que se toma como referencia para construir una |URL| absoluta a partir de una |URL| relativa. Son de dos tipos: + De *archivo* como: .. code-block:: none http://docs.iescdl.es/~josem/XML/07.html/01.intro.html + De *directorio* como: .. code-block:: none http://docs.iescdl.es/~josem/XML/08.css/ Se diferencian unas de otras en que las |URL| base de directorio siempre acaban con una barra. Las |URL|\ s relativas se utilizan cuando desde un documento se refiere otro. Cuando es así, la |URL| base es la |URL| absoluta del propio documento\ [#]_ y la |URL| relativa podrá adoptar dos formas: :dfn:`URL relativa absoluta` (terminología propia) Es aquella que empieza por una '/' y equivale a la |URL| absoluta que se obtiene de concatenar el esquema y la máquina de la |URL| base a la propia |URL| relativa. Por ejemplo: .. table:: :class: html-url-base ============================================= ============== =================================== URL Base URL relativa URL absoluta --------------------------------------------- -------------- ----------------------------------- https://docs.iescdl.es/~josem/XML/index.html /a/b/c.html https://docs.iescdl.es/a/b/c.html ============================================= ============== =================================== :dfn:`URL relativa relativa` (terminología propia) Es aquella que no empieza por '/' y equivale a la |URL| absoluta que se obtiene de concatenar la |URL| base con la |URL| relativa, sabiendo que en el caso que la |URL| base sea de archivo, hay que eliminar el propio nombre del archivo. Como en el caso de las rutas *UNIX* el directorio :code:`..` equivale al directorio padre. .. table:: :class: html-url-base ============================================= ============== ======================================== URL Base URL relativa URL absoluta ============================================= ============== ======================================== https://docs.iescdl.es/~josem/XML/index.html c.html https://docs.iescdl.es/~josem/XML/c.html https://docs.iescdl.es/~josem/XML/index.html ../c.html https://docs.iescdl.es/~josem/c.html https://docs.iescdl.es/~josem/XML/index.html https://docs.iescdl.es/~josem/index.html https://docs.iescdl.es/~josem/ c.html https://docs.iescdl.es/~josem/c.html ============================================= ============== ======================================== .. note:: Como puede apreciarse la cadena vacía es una |URL| relativa válida y equivale a una |URL| absoluta igual a la |URL| base. Enlaces internos ---------------- Es muy frecuente que al incluir un hipervínculo queramos enlazar no ya con una página |HTML|, sino con una parte concreta de la página |HTML|. Para ello, es necesario que la página destino contenga elementos que se hayan marcado con identificadores: .. code-block:: html

Los mamíferos

Bla, bla, bla

Los homínidos

Bla, bla, bla

Los felinos

Bla, bla, bla

Hecho así, para que el hipervínculo enlace directamente con el elemento interno deseado, basta con añadir :code:`#mamiferos` a la |URL| si es que se quiere enlazar con la sesión dedicada a los mamíferos, ya que este es el valor que hemos dado al identificador correspondiente. Por tanto: .. code-block:: none http://www.losanimales.org/descripcion.html#mamiferos podría ser una |URL| absoluta válida. Mientras que: .. code-block:: none #mamiferos podría ser el valor de un hipervínculo válido si el enlace está en la propia página. Otros hipervínculos ------------------- Además de las rutas anteriores en las que siempre se ha presupuesto que el protocolo era |HTTP| o |HTTP|\ s, para cuyo destino el agente apropiado es el propio navegador, existen otros tipos de recursos externos accesibles por distintos medios. Tradicionalmente, estos se han reducido a dos: |FTP| (para cuyo protocolo los navegadores también solían traer soporte) y correo electrónico:: FTP de rediris Email de contacto Si la configuración es adecuada, en el segundo caso el navegador se encarga de invocar al programa de correo electrónico. Pero con la proliferación de los teléfonos inteligentes, los enlaces ajenos al navegador han proliferado y pueden adoptar muchas formas:: Teléfono de contacto Contacto a través de Skype Envíar SMS .. seealso:: En `este tutorial `_ se explica cómo incluir en un enlace *mailto:* asunto, destinatario, etc. .. _html-data-uris: Data |URI|\ s ------------- Una página |HTML| es un documento de texto que suele referir distintos contenidos de diverso tipo (*scripts*, hojas de estilos, imágenes, etc.). Todos estos contenidos se obtienen gracias a la indicación de su |URL| absoluta o relativa: .. code-block:: html Logo de HTML5 |HTML|\ 5 incorpora un mecanismo, llamado datos |URI|\ s, para sustituir la |URL| por el contenido del archivo, de suerte que el archivo queda embebido dentro del propio documento |HTML|. Puede llegar a ser muy útil en algunos casos, como cuando se necesita cambiar al vuelo una imagen vectorial en función de las acciones del usuario. El formato de estos data |URI|\ s es el siguiente: .. code-block:: none data:tipo-mime[;base64], Como por ejemplo: .. code-block:: html donde en este caso el tipo |MIME| es "`application/javascript`" y los datos un minúsculo código *Javascript*, que hubiera estado incluido en un archivo, si no hubieramos hecho uso de un data |URI|. La `codificación en base64 `_\ [#]_ es útil cuando los datos son binarios (p.e. si representamos una imagen |PNG|). Por ejemplo, el ejemplo anterior para incrustar el logo de |HTML|\ 5, podría escribirse así: .. code-block:: html Logo de HTML5 .. _html-vers: Versiones ========= Tim Berners-Lee creó el |HTML| en 1990 como un dialecto |SGML|, aunque sin una definición formal mediante |DTD|. En 1993 se publicó como borrador una especificación que sí incluía un |DTD|, por lo que se puede considerar que es a partir de esa fecha cuando |HTML| pasa a ser formalmente un dialecto |SGML|. Se publican posteriormente tres versiones del lenguaje, ya definido como |SGML|: * |HTML| **2.0**, en 1995, que es la primera especificación formal del lenguaje. * |HTML| **3.2**, en 1997, que fue publicada ya por el |W3C|. * |HTML| **4.01**. en 1999. |HTML|\ 4 En esta última versión, el |W3C| intentó desligar la definición estructural (reservada para |HTML|) de la visual (reservada para |CSS|), por lo que se propuso ir eliminando las marcas y atributos |HTML| que definían aspecto, marcándolas como obsoletas. Para hacer menos traumático el cambio definió tres versiones del estándar: * :dfn:`Frameset`, que permitía el uso de :ref:`iframes ` y elementos y atributos obsoletos: .. code-block:: dtd * :dfn:`Transitional`, que permitía el uso de elementos y atributos obsoletos: .. code-block:: dtd * :dfn:`Strict`, que no permitía el uso de elementos obsoletos: .. code-block:: dtd En principio, la versión recomendada por el |W3C| era esta última. |XHTML| En este punto (1999), el |W3C|, que era el encargado de desarrollar el lenguaje, pretendió darle un giro y adaptarlo a las especificaciones |XML|, que habían sido publicadas por este mismo organismo también en 1999. Como consecuencia reformuló |HTML| **4.01** para adaptarlo a las reglas del |XML| y publicó en 2000 la especificación |XHTML| **1.0**. Al ser una reformulación, también disponía de las tres versiones: .. code-block:: dtd Los esfuerzos entonces del |W3C| se centraron en el desarrollo del lenguaje como dialecto |HTML|, esto es, en el |XHTML| y abandonaron por completo el sabor |SGML| que quedó estancado en la versión **4.01**. En consecuencia en 2001 publicó |XHTML| **1.1** en que ya sólo había una única versión: .. code-block:: dtd |HTML|\ 5 El |W3C| continuó en los años siguientes el desarrollo de |XHTML| **2** del que llegó a publicar borradores, abandonando por completo |HTML|. Como respuesta a esta política de abandonar |HTML|, surgió en 2004 el |WHATWG|\ [#]_, un grupo que aglutinaba a los principales creadores de navegadores web\ [#]_ y que en contra de los deseos del |W3C|, que abogaba por |XHTML|, quería seguir desarrollando |HTML|. Comenzó entonces un pulso entre ambos grupos, que venció el |WHATWG| al admitir el |W3C| en 2007 la creación de un grupo de trabajo en su seno sobre |HTML|. Este grupo en enero de 2008 publicó el primer borrador de la especificación de |HTML|\ 5, mientras que el `último borrador de XHTML `_ se había publicado en 2006 y nunca se llegó a publicar el siguiente que debía haber aparecido en julio de 2009. De hecho, en 2009 el |W3C| decidió que a final de año se disolviera el grupo de trabajo sobre |XHTML| lo que suponía oficialmente reconocer que él único estándar reconocido sería |HTML|\ 5. En 2014, apareció la primera recomendación oficial del |W3C| sobre |HTML| **5.0**. .. note:: En un primer momento, |WHATWG| optó por hacer del estándar |HTML| una `norma viva `_, esto es, una versión que no se atiende a números sino que está en continuo proceso de redacción. De hecho, la norma ni siquiera refiere el **5** en su título. El |W3C|, en cambio, optó por publicar cada cierto tiempo una versión númerada. Fue así como publicó **5.0** en 2014, **5.1** en 2016 y **5.2** en 2018, versiones que se basaban en la versión viva y lo que realmente los navegadores implementaban de esa versión viva. Sin embargo, a comienzos de 2021 `se renunció a publicar la versión 5.3 `_ y dejó de publicar versiones numeradas, por lo que sólo la norma viva del |WHATWG| es la referencia actual del lenguaje. |HTML|\ 5 introdujo **novedades** substanciosas (por no decir disruptivas) sobre las versiones anteriores de |HTML|: * Introdujo una |API| que posibilitara el desarrollo de aplicaciones web complejas. Esa es la razón por la que *Javascript* se pudo incorporar plenamente como tecnología web y hemos conocido cómo se han desarrollado auténticas aplicaciones que ejecutamos en el propio navegador. * Soporte nativo para contenido gráfico y multimedia con elementos como :ref:`video `, :ref:`audio ` o ````. * Soporte para |SVG| y MathML_. * Virar el lenguaje |HTML| hacia la creación de documento plenamente semántico con etiquetas como :ref:`article `, :ref:`section `, :ref:`nav `, etc. Esta es la historia, pero ¿es |HTML|\ 5 entonces |SGML|? La respuesta es que **no**. |HTML| no es ya |SGML|, porque no hay definido ningún |DTD| para su validación y, además, es imposible definir uno, ya que hay ciertas reglas que son inexpresables con la sintaxis del |DTD|. Esa es la razón por la que `la declaración de tipo de documento `_ es, simplemente: .. code-block:: dtd que ni siquera es una declaración |SGML| válida. .. seealso:: Consulte `esta respuesta de stackoverflow `_ para más información. Por otro lado, el propio estándar define dos sintaxis distintas para la norma |HTML|: * La sintaxis |HTML|, asociada al tipo |MIME| *text/html*. * La sintaxis |XML|, asociada al tipo |MIME| *application/xhtml+xml*, para la que no hay tampoco |DTD| y que consiste básicamente en `adaptar la sintaxis HTML a otra que sea bien formada para un procesador XML `_. Comúnmente se llama a esta sintaxis |XHTML|\ 5. Los apuntes se centrarán en la sintaxis |HTML|, aunque se definirán más adelante :ref:`las pautas para saber escribir con sintaxis XML `. .. seealso:: Eche un vistazo a la representación gráfica de `la evolución de las tecnologías web `_. Tecnologías asociadas ===================== El servicio de páginas web no se restringe exclusivamente al uso del |HTML|, sino que hay multiples tecnologías implicadas. Las más destacadas son: * :ref:`CSS ` para aplicar aspecto visual al código |HTML|. * Javascript_ (cuyo estándar recibe el nombre de ECMAScript_), que se usa como lenguaje en el lado del cliente, esto es, en el propio navegador a fin de dotar de dinamismo a las páginas. Es posible crear auténticas aplicaciones web que se ejecutan integramente en el ordenador del cliente con sólo unos pocos datos que se reciban del servidor. * Lenguajes de programación en el lado del servidor que hacen de enlace entre el servidor y las bases de datos. La estrategia puede variar: - desde generar toda la página web en el servidor y transferirla al cliente completa. - a limitarse básicamente a servir datos en un formato adecuado (:ref:`XML `, :ref:`JSON `) y construir la página en el cliente gracias a Javascript_. Los lenguajes de servidor más utilizados son el propio Javascript_ (usando NodeJS_), |PHP|, Python_ y Java_. .. _html-tools: Herramientas ============ Para hacer más sencilla la escritura de nuestro documentos, podemos hacer uso de algunas herramientas: Edición ------- Para escribir los documentos |HTML| (y |CSS|) es indispensable usar al menos editores de texto con resaltado de sintaxis. Son alernativas: * vim_, el editor. * nano_, básico, pero suficiente. * :ref:`Visual Studio Code `, que ya hemos utilizado al escribir |XML|, |YAML| o |JSON| y al que podemos añadirle alguna configuración adicional para :ref:`facilitar la escritura de HTML `. Lo tomaremos como editor de referencia también para este bloque de tecnologías web. .. _html-validacion: Validación ---------- Es muy conveniente comprobar la validez de los documentos |HTML| para lo cual podemos usar validadores en línea como: **HTML** * `validator.nu `_. * `El validador del W3C `_. Existen también extensiones para navegadores (como Validity_ para Chromium_) que permiten la comprobación de la página que se está viendo en la pestaña activa. Por lo general, sin embargo, no permiten la validación de documentos locales. **CSS** * `El validador CSS del W3C `_. .. note:: Si se usa :program:`Visual Studio Code` pueden integrarse estas validaciones dentro del propio editor. Consulte ls :ref:`instrucciones para escribir con él HTML `. Recetarios ---------- Los recetarios presentan de modo resumido los elementos del lenguaje a fin de ofrecer una referencia rápida. Existen muchos: **HTML** * `websitesetup,org (HTML) `_. De entre los ofrecidos, salvamos el :download:`formato PNG `. * `algonquindesign.ca `_ **CSS** * `websitesetup,org (CSS) `_. De entre los ofrecidos, salvamos el :download:`formato PDF `. Visualización ------------- Para comprobar nuestras páginas |HTML| es obvio que necesitamos un navegador reciente que soporte convenientemente |HTML|\ 5 y |CSS|\ 3. Cualquiera de los más usados debería valernos: * Chromium_ (o derivados). * Firefox_ (o derivados). * Safari_. En principio, nos bastará con almacenar en el disco local los archivos y acceder a ellos abriéndolos con el navegador. Si usamos :program:`Visual Studio Code`, tendremos :ref:`facilidades para realizar la operación `. Ver archivos, locales, sin embargo no supone una transferencia |HTTP|, lo cual tiene importancia, pero no para los objetivos del curso que son modestos. En cualquier caso, es posible improvisar un miniservidor web para alojar nuestras páginas: * :program:`Visual Studio Code` nos lo permite a través de la extensión `Live Preview `_. * Una alternativa universal es montar un modesto servidor con Python, para lo cual podemos hacer lo siguiente: .. code-block:: console $ cd /ruta/a/los/ficheros $ python3 -m http.server 8080 Y listo. Un servidor web local escuchando en el puerto **8080**. Sea como sea, los ordenadores modernos incluyen todos una **herramienta de desarrollador** a la cual (al menos en derivados de Firefox_ y Chromium_) se accede pulsando :kbd:`Ctrl`\ +\ :kbd:`Shift`\ +\ :kbd:`i`, o bien, colocándonos sobre alguna parte de la página web y abriendo el menú contextual eligiendo "*Inspeccionar*". En este segundo caso, la herramienta se abrirá en la pestaña en la que se presenta el |DOM| completo y justamente seleccionado el elemento |HTML| correspondiente. Es muy potente y nos permite: * Consultar y alterar el |DOM|. * Consultar y alterar los documentos adicionales cargados (p.e. alguna propiedad |CSS|). * Analizar la carga de archivos. * Abrir una consola de *Javascript* y ejecutar código. * etc. .. seealso:: Si quiere profundizar en esta fantástica herramienta, puede echarle un vistazo a `este artículo de MDN sobre la herramienta de Firefox `_. En realidad, todas funcionan de forma semejante, así que puede valernos su lectura aunque utilicemos otro navegador. Pruebas de concepto ------------------- Es frecuente que, cuando creamos documentos web, necesitemos realizar una prueba de concepto sobre algún particular de |HTML|, |CSS| o Javascript_. Por supuesto, podemos hacer pruebas sobre un documento local, pero existen páginas en internet que nos permiten realizarlas directamente sobre ellas y compartir el resultado con otros desarrolladores: jsfiddle.net_ Es un sitio web que permite crear pruebas de concepto en |HTML|, |CSS| y Javascript_, y compartirlas con otros desarrolladores, bien para resolver dudas ajenas, bien para resolver las propias. Por ejemplo, esta es `una prueba con jsfiddle `_ e incluso se puede obtener el |HTML| que genera la prueba `añadiendo /show a la dirección `_ y guardando el *frame* apropiado. codepen.io_ Sitio alternativo al anterior con el mismo propósito y las mismas funcionalidades. Esto, por ejemplo sería `una prueba en codepen.io `_ jsbin.com_ Sitio semejante a los dos anteriores, aunque presenta algunas particularidades como una consola de Javascript_. mdn_ Otra alternativa más incluida en el sitio de |MDN|. .. rubric:: Notas al pie .. [#] A menos que se haya cambiado a través del elemento |base|. .. [#] En un sistema *Linux* es posible generar la codificación en base64 de un archivo con la orden :program:`base64`: .. code-block:: console $ base64 html5.png .. [#] En 2004, la `Fundación Mozilla`_ y Opera_ presentaron un *paper* en un taller organizado por el |W3C| centrado en el desarrollo de tecnologías que mantuvieran la compatibilidad con el |HTML| de los navegadores. Este *paper*, sin embargo, fue rechazado. Este rechazo fue lo que originó la creación del |WHATWG|. .. [#] En aquel entonces, trabajadores de Apple_ (que desarrollaba Safari_), la `fundación Mozilla`_ y Opera_. Se invitó también a personal de Microsoft_ (porque desarrollaba `Internet Explorer`_), pero no se incorpó. Google_ por aquel entonces aún no había empezado el desarrollo de Chromium_. .. |URI| replace:: :abbr:`URI (Uniform Resource Identifier)` .. |FTP| replace:: :abbr:`FTP (File Transfer Protocol)` .. |IP| replace:: :abbr:`IP (Internet Protocol)` .. |W3C| replace:: :abbr:`W3C (W3 Consortium)` .. |WHATWG| replace:: :abbr:`WHATWG (Web Hypertext Application Technology Working Group)` .. |MIME| replace:: :abbr:`MIME (Multipurpose Internet Mail Extensions)` .. |PHP| replace:: :abbr:`PHP (PHP Hypertext Preprocessor)` .. |PNG| replace:: :abbr:`PNG (Portable Network Graphic)` .. |HTTP| replace:: :abbr:`HTTP (HyperText Transfer Protocol)` .. |CSS| replace:: :abbr:`CSS (Cascading Style Sheets)` .. |XHTML| replace:: :abbr:`XHTML (eXtensible HyperText Markup Language)` .. |SGML| replace:: :abbr:`SGML (Standard Generalized Markup Language)` .. |DTD| replace:: :abbr:`DTD (Document Type Definition)` .. |URN| replace:: :abbr:`URN (Uniform Resource Name)` .. |YAML| replace:: :abbr:`YAML (YAML Ain't Markup Language)` .. |DOM| replace:: :abbr:`DOM (Document Object Model)` .. |MDN| replace:: :abbr:`MDN (Mozilla Developer Network)` .. |API| replace:: :abbr:`API (Application Programming Interface)` .. |SVG| replace:: :abbr:`SVG (Scalable Vector Graphics)` .. |base| replace:: :ref:` ` .. _Apple: https://www.apple.com .. _Safari: https://es.wikipedia.org/wiki/Safari_(navegador) .. _Opera: https://es.wikipedia.org/wiki/Opera_Software .. _Microsoft: https://www.microsoft.com .. _Google: https://www.google.com/about/ .. _Fundación Mozilla: https://www.mozilla.org/es-ES/about/ .. _Internet Explorer: https://es.wikipedia.org/wiki/Internet_Explorer .. _ECMAScript: https://es.wikipedia.org/wiki/ECMAScript .. _NodeJS: https://nodejs.org/ .. _Python: https://www.python.org .. _Java: https://es.wikipedia.org/wiki/Java_(lenguaje_de_programaci%C3%B3n) .. _vim: http://www.vim.org .. _nano: https://www.nano-editor.org/ .. _notepad++: https://notepad-plus-plus.org/ .. _Validity: https://www.validity.org.uk/ .. _Chromium: https://www.chromium.org/ .. _Safari: https://es.wikipedia.org/wiki/Safari_(navegador) .. _Firefox: https://es.wikipedia.org/wiki/Mozilla_Firefox .. _MathML: https://www.w3.org/TR/MathML .. _jsfiddle.net: https://jsfiddle.net/ .. _codepen.io: https://codepen.io/ .. _jsbin.com: https://jsbin.com .. _Visual Studio Code: https://code.visualstudio.com/ .. _mdn: https://developer.mozilla.org/en-US/play