2.5 Plantillas
Un tema de Hugo consta de dos componentes principales: plantillas y archivos web. El primero es esencial y le dice a Hugo cómo presentar una página.24 El último es opcional pero también importante. Por lo general, consta de archivos CSS y JavaScript, así como otros recursos, como imágenes y videos. Estos activos determinan la apariencia y la funcionalidad de su sitio web, y algunos pueden estar integrados en el contenido de sus páginas web.
Puede obtener más información sobre las plantillas de Hugo en la documentación oficial (https://gohugo.io/templates/overview/). Hay muchos tipos diferentes de plantillas. Para que le resulte más fácil dominar las ideas clave, creé un tema de Hugo muy mínimo, que cubre la mayoría de las funcionalidades que un usuario promedio puede necesitar, pero el número total de líneas es de solo 150, por lo que podemos hablar de todas las fuentes código de este tema en la siguiente subsección.
2.5.1 Un pequeño ejemplo
XMin es un tema de Hugo. Lo escribí desde cero en aproximadamente 12 horas. Aproximadamente media hora se gastó en plantillas, se dedicaron 3,5 horas a modificar los estilos CSS y se gastaron 8 horas en la documentación (https://xmin.yihui.name). Creo que este puede ser un caso representativo de cuánto tiempo pasaría en cada parte cuando diseñe un tema. Está, quizás, en nuestra naturaleza pasar mucho más tiempo en cosas cosméticas como CSS que en cosas esenciales como plantillas. Mientras que la codificación es, a menudo, más fácil que la documentación.
Mostraremos el código fuente del tema XMin. Debido a que el tema puede actualizarse ocasionalmente en el futuro, puede seguir este enlace para obtener una versión fija de la que hablaremos en esta sección: https://github.com/yihui/hugo-xmin/tree/4bb305. A continuación se muestra una vista en árbol de todos los archivos y directorios del tema:
hugo-xmin/
├── LICENSE.md
├── README.md
├── archetypes
│ └── default.md
├── layouts
│ ├── 404.html
│ ├── _default
│ │ ├── list.html
│ │ ├── single.html
│ │ └── terms.html
│ └── partials
│ ├── foot_custom.html
│ ├── footer.html
│ ├── head_custom.html
│ └── header.html
├── static
│ └── css
│ ├── fonts.css
│ └── style.css
└── exampleSite
├── config.toml
├── content
│ ├── _index.md
│ ├── about.md
│ ├── note
│ │ ├── 2017-06-13-a-quick-note.md
│ │ └── 2017-06-14-another-note.md
│ └── post
│ ├── 2015-07-23-lorem-ipsum.md
│ └── 2016-02-14-hello-markdown.md
├── layouts
│ └── partials
│ └── foot_custom.html
└── public
└── ...
LICENSE.md
y README.md
no son componentes necesarios de un tema, pero definitivamente debe elegir una licencia para su código fuente para que otras personas puedan usar su código correctamente, y un README
puede ser la breve documentación de su software.
El archivo archetypes/default.md
define la plantilla predeterminada en función de qué usuarios pueden crear nuevas publicaciones. En este tema, default.md
solo proporcionaba metadatos YAML vacíos:
Los directorios más importantes de un tema son layouts/
y static/
. Las plantillas HTML se almacenan en layouts/
, y los archivos se almacenan en static/
.
Para comprender layouts/
, debe conocer algunos conceptos básicos sobre HTML (consulte la sección B.1) porque las plantillas en este directorio son, en su mayoría, documentos o fragmentos HTML. Hay muchos tipos posibles de subdirectorios en layouts/
, pero solo vamos a introducir dos aquí: _default/
y partials/
.
El directorio
_default/
es donde almacena las plantillas predeterminadas para sus páginas web. En el tema XMin, tenemos tres plantillas:single.html
,list.html
, yterms.html
.single.html
es una plantilla para presentar páginas individuales. Una sola página básicamente corresponde a un documento de Markdown bajocontent/
, y contiene tanto los metadatos (YAML) como el contenido. Por lo general, queremos mostrar el título de la página, el autor, la fecha y el contenido. A continuación se muestra el código fuente desingle.html
de XMin:{{ partial "header.html" . }} <div class="article-meta"> <h1><span class="title">{{ .Title }}</span></h1> {{ with .Params.author }} <h2 class="author">{{ . }}</h2> {{ end }} {{ if .Params.date }} <h2 class="date">{{ .Date.Format "2006/01/02" }}</h2> {{ end }} </div> <main> {{ .Content }} </main> {{ partial "footer.html" . }}
Verá muchos pares de corchetes
{{}}
, y así es como se programan las plantillas usando las variables y funciones de Hugo.La plantilla comienza con una plantilla parcial
header.html
, para la cual verá el código fuente pronto. Por ahora, puede imaginarlo como todas las etiquetas HTML antes del cuerpo de su página (e.g.,<html><head>
). Ls plantillas parciales se usan, principalmente, para reutilizar código HTML. Por ejemplo, todas las páginas HTML pueden compartir tags muy similares<head></head>
, y puede factorizar las partes comunes en plantillas parciales.Los metadatos de una página se incluyen en un elemento
<div>
con la clasearticle-meta
. Recomendamos que asigne clases a elementos HTML al diseñar plantillas, de modo que sea más fácil aplicar estilos CSS a estos elementos usando nombres de clase. En una plantilla, tiene acceso a muchas variables proporcionadas por Hugo, por ejemplo, la variable.Title
almacena el valor del título de la página, y escribimos el título en<span>
en un encabezado de primer nivel<h1>
. De forma similar, el autor y la fecha se escriben en<h2>
, pero solo si se proporcionan en los metadatos YAML. La sintaxis{{ con FOO }}{{ . }}{{ end }}
es una abreviatura de{{si FOO }}{{ FOO }}{{ end }}
, es decir, le ahorra el esfuerzo de digitar la expresiónFOO
dos veces usando{{ . }}
. El método.Format
se puede aplicar a un objeto de fecha, y en este tema, formateamos las fechas en el formatoYYYY/mm/dd
(2006/01/02
es la forma de especificar el formato en Go) .Luego mostramos el contenido de una página, que se almacena en la variable
.Content
. El contenido está envuelto en una etiqueta HTML semántica<main>
.La plantilla finaliza después de incluir otra plantilla parcial
footer.html
(código fuente que se mostrará en breve).Para que sea más fácil de entender cómo funciona una plantilla, mostramos un mínimo ejemplo de publicación a continuación:
Con la plantilla
single.html
, se convertirá en una página HTML con un código fuente que se parece más o menos a esto (con el encabezado y el pie de página omitidos):<div class="article-meta"> <h1><span class="title">Hello World</span></h1> <h2 class="author">Frida Gomam</h2> <h2 class="date">2017/06/19</h2> </div> <main> <p>A single paragraph.</p> </main>
Para un ejemplo completo de una página sencilla, puede ver https://xmin.yihui.name/about/.
list.html
es la plantilla para generar listas de páginas, como una lista de publicaciones de blog, o una lista de páginas dentro de una categoría o etiqueta. Aquí está su código fuente:{{ partial "header.html" . }} {{if not .IsHome }} <h1>{{ .Title }}</h1> {{ end }} {{ .Content }} <ul> {{ range (where .Data.Pages "Section" "!=" "") }} <li> <span class="date">{{ .Date.Format "2006/01/02" }}</span> <a href="{{ .URL }}">{{ .Title }}</a> </li> {{ end }} </ul> {{ partial "footer.html" . }}
Nuevamente, usa dos plantillas parciales
header.html
yfooter.html
. La expresión{{if not .IsHome}}
significa, si esta lista no es la página de inicio, muestre el título de la página. Esto es porque no quiero mostrar el título en la página de inicio. Es solo mi preferencia personal. Sin duda, puede mostrar el título en<h1>
en la página de inicio, si lo desea.El
{{.Content}}
muestra el contenido de la lista. Tenga en cuenta que típicamente.Content
está vacío, lo que puede sorprender. Esto se debe a que una página de lista no se genera a partir de un archivo de marca de origen de forma predeterminada. Como sea, hay una excepción. Cuando se escribe un archivo Markdown especial_index.md
en un directorio correspondiente al nombre de la lista, el.Contenido
de la lista será el contenido de este archivo Markdown. Por ejemplo, puede definir el contenido de su página de inicio encontent/_index.md
, y el contenido de la página de la lista de publicaciones encontent/post/_index.md
.A continuación, generamos la lista utilizando un bucle (
range
) a través de todas las páginas filtradas por la condición de que la sección de una página no debe estar vacía. “Section” en Hugo significa el nombre del subdirectorio de primer nivel bajocontent/
. Por ejemplo, la sección decontent/post/foo.md
espost
. Por lo tanto, el filtro significa que enumeraremos todas las páginas bajo subdirectorios decontent/
. Esto excluirá las páginas debajo del directorio raízcontent/
, comocontent/about.md
.Tenga en cuenta que la variable
.Data
es dinámica y su valor cambia de acuerdo con la lista específica que desea generar. Por ejemplo, la página de la lista https://xmin.yihui.name/post/ solo contiene páginas bajocontent/post/
, y https://xmin.yihui.name/note/ solo contiene páginas bajocontent/note/
. Estas páginas de lista son generadas automáticamente por Hugo, y no necesita pasar explícitamente por las seccionespublicación
ynota
. Es decir, una sola plantillalist.html
generará múltiples listas de páginas según las secciones y los términos de taxonomía (por ejemplo, categories y tags) que tenga en su sitio web.Los elementos de la lista están representados por las etiquetas HTML
<li>
en<ul>
. Cada elemento consta de la fecha, el enlace y el título de una página. Puede ver https://xmin.yihui.name/post/ para obtener un ejemplo completo de una página de lista.terms.html
es la plantilla para la página de inicio de los términos de la taxonomía. Por ejemplo, puede usarlo para generar la lista completa de categorías o etiquetas. El código fuente está a continuación:{{ partial "header.html" . }} <h1>{{ .Title }}</h1> <ul class="terms"> {{ range $key, $value := .Data.Terms }} <li> <a href='{{ (print "/" $.Data.Plural "/" $key) | relURL }}'> {{ $key }} </a> ({{ len $value }}) </li> {{ end }} </ul> {{ partial "footer.html" . }}
Similar a
list.html
, también usa un bucle. La variable.Data.Terms
almacena todos los términos bajo una taxonomía, por ejemplo, todos los nombres de categorías. Puede considerarlo como una lista con nombre en R (llamado ‘map’ en Go), cuyos nombres son los términos y los valores son listas de páginas. La variable$key
denota el término y$value
denota la lista de páginas asociadas con este término. Lo que presentamos en cada<li>
es un enlace al término página, así como el recuento de publicaciones que utilizan este término (len
es una función Go que devuelve la longitud de un objeto).Hugo representa automáticamente todas las páginas de taxonomía, y los nombres de ruta son las formas plurales de las taxonomías, por ejemplo, https://xmin.yihui.name/categories/ y https://xmin.yihui.name/tags/. Ese es el significado de
.Data.Plural
. El$
inicial es obligatorio porque estamos dentro de un bucle y necesitamos acceder a variables del alcance externo. El enlace del término se pasa a la función HugorelURL
a través de una conector|
para hacerlo relativo, lo cual es una buena práctica porque los enlaces relativos son más portátiles (independientemente del nombre de dominio).
El directorio
parials/
es el lugar para poner los fragmentos HTML para ser reutilizados por otras plantillas a través de la funciónpartial
. Tenemos cuatro plantillas parciales bajo este directorio:header.html
define la etiqueta<head>
y el menú de navegación en la etiqueta<nav>
.<!DOCTYPE html> <html lang="{{ .Site.LanguageCode }}"> <head> <meta charset="utf-8"> <title>{{ .Title }} | {{ .Site.Title }}</title> <link href='{{ "/css/style.css" | relURL }}' rel="stylesheet" /> <link href='{{ "/css/fonts.css" | relURL }}' rel="stylesheet" /> {{ partial "head_custom.html" . }} </head> <body> <nav> <ul class="menu"> {{ range .Site.Menus.main }} <li><a href="{{ .URL | relURL }}">{{ .Name }}</a></li> {{ end }} </ul> <hr/> </nav>
El área
<head>
debe ser fácil de entender si está familiarizado con HTML. Tenga en cuenta que también incluimos una plantilla parcialhead_custom.html
, que está vacía en este tema, pero hará que sea mucho más fácil para los usuarios agregar código personalizado a<head>
sin reescribir toda la plantilla. Ver la sección @ref(layouts personalizados) para más detalles.El menú de navegación es esencialmente una lista, y cada elemento de la lista se lee de la variable
.Site.Menus.main
. Esto significa que los usuarios pueden definir el menú enconfig.toml
, e.g.,Esto generará un menú como:
Hugo tiene un poderoso sistema de menú, y solo usamos el tipo más simple de menú en este tema. Si está interesado en más funciones como menús anidados, consulte la documentación completa en http://gohugo.io/extras/menus/.
footer.html
define el área footer de una página y cierra el documento HTML:
<footer> {{ partial "foot_custom.html" . }} {{ with .Site.Params.footer }} <hr/> {{ . | markdownify }} {{ end }} </footer> </body> </html>
El propósito de la plantilla parcial
foot_custom.html
es el mismo quehead_custom.html
; es decir, para permitir que el usuario agregue código personalizado al<footer>
sin volver a escribir la plantilla completa.Por último, usamos la variable
.Site.Params.footer
para generar un pie de página. Tenga en cuenta que utilizamos la funciónwith
nuevamente. Recuerde que la sintaxis{{with .Site.Params.footer}}{{ . }}{{ end }}
es una abreviatura de{{if .Site.Params.footer }}{{.Site.Params.footer }}{{ end }}
. Esta sintaxis le evita escribir dos veces la expresión.Site.Params.footer
usando{{ . }}
como un marcador de posición para la variablefooter
, que se define como un parámetro de sitio en nuestro archivoconfig.toml
. La función adicionalmarkdownify
puede convertir Markdown a HTML (es decir,{{ . | markdownify}}
. En conjunto, esta secuencia significa que podemos definir una opciónfooter
usando Markdown bajoparams
enconfig.toml
, e.g.,
Hay una plantilla especial 404.html
, que Hugo usa para crear la página 404 (cuando no se encuentra una página, se muestra esta página):
Con todas las plantillas anteriores, podremos generar un sitio web a partir de los archivos fuente de Markdown. Sin embargo, es poco probable que esté satisfecho con el sitio web porque los elementos HTML no tienen ningún estilo y la apariencia predeterminada puede no parecer atractiva para la mayoría de las personas. Puede haber notado que en header.html
, hemos incluido dos archivos CSS, /css/style.css
y /css/fonts.css
.
Puede encontrar muchos frameworks CSS de código abierto existentes que se pueden aplicar a un tema de Hugo. Por ejemplo, el framework CSS más popular puede ser Bootstrap: http://getbootstrap.com. Cuando estaba diseñando XMin, me preguntaba hasta dónde podría llegar sin usar ninguno de estos frameworks existentes, porque generalmente son muy grandes. Por ejemplo, bootstrap.css
tiene casi 10000 líneas de código cuando no se minimiza. Resultó que pude obtener una apariencia satisfactoria con aproximadamente 50 líneas de CSS, que explicaré en detalle a continuación:
style.css
define todos los estilos excepto las fuentes tipográficas:El ancho máximo del cuerpo de la página se establece en 800 píxeles porque una página excesivamente ancha es difícil de leer (
800
es un umbral arbitrario que elegí). El cuerpo se centra utilizando el truco de CSSmargin: auto
, lo que significa que los márgenes superior, derecho, inferior y izquierdo son automáticos. Cuando los márgenes izquierdo y derecho de un elemento de bloque sonauto
, estará centrado./* header and footer areas */ .menu li { display: inline-block; } .article-meta, .menu a { text-decoration: none; background: #eee; padding: 5px; border-radius: 5px; } .menu, .article-meta, footer { text-align: center; } .title { font-size: 1.1em; } footer a { text-decoration: none; } hr { border-style: dashed; color: #ddd; }
Recuerde que nuestro elemento de menú es una lista
<ul class="menu">
definida enheader.html
. Cambié el estilo de visualización predeterminado de<li>
dentro del menú ainline-block
, de modo que se distribuyan de izquierda a derecha como elementos en línea, en lugar de apilarse verticalmente como una lista de viñetas (el comportamiento predeterminado))La regla horizontal (
<hr>
) se establece en una línea discontinua de color gris claro para que sea menos prominente en una página. Estas reglas se utilizan para separar el cuerpo del artículo de las áreas de encabezado y pie de página./* code */ pre { border: 1px solid #ddd; box-shadow: 5px 5px 5px #eee; padding: 1em; overflow-x: auto; } code { background: #f9f9f9; } pre code { background: none; }
Para bloques de código (
<pre>
), aplico bordes gris claro con efectos de sombra paralela. Cada elemento de código en línea tiene un fondo gris muy claro. Estas decoraciones son simplemente por mi propio interés y énfasis peculiares en el código./* misc elements */ img, iframe, video { max-width: 100%; } main { hyphens: auto; } blockquote { background: #f9f9f9; border-left: 5px solid #ccc; padding: 3px 1em 3px; } table { margin: auto; border-top: 1px solid #666; border-bottom: 1px solid #666; } table thead th { border-bottom: 1px solid #ddd; } th, td { padding: 5px; } tr:nth-child(even) { background: #eee }
Los elementos incrustados, como las imágenes y los videos que exceden el margen de la página, a menudo son desagradables, por lo que restrinjo su ancho máximo al 100%. La separación silábica está activada para palabras en
<main>
. Las citas en bloque tienen una barra lateral izquierda gris y un fondo gris claro. Las tablas están centradas de manera predeterminada, con solo tres reglas horizontales: los bordes superior e inferior de la tabla y el borde inferior de la tabla. Las filas de la tabla están rayadas para facilitar la lectura de la tabla, especialmente cuando la tabla es ancha.fonts.css
es una hoja de estilo separada porque juega un papel crítico en la apariencia de un sitio web, y es muy probable que desee personalizar este archivo. En la mayoría de los casos, sus lectores dedicarán la mayor parte del tiempo a leer el texto en sus páginas, por lo que es importante hacer que el texto sea cómodo de leer. No soy un experto en diseño web, y acabo de elegir Palatino para el cuerpo y Lucida Console o Monaco (cualquiera que esté disponible en su sistema) para el código. Es común usar las fuentes web de Google hoy en día. Puede probar algunas fuentes web y ver si le gusta alguno de ellos.
Los dos archivos CSS se colocan bajo el directorio static/css/
del tema. En la plantilla HTML header.html
, la ruta /css/style.css
se refiere al archivo static/css/style.css
.
Por último, este tema proporcionó un sitio de ejemplo en exampleSite/
. La estructura del directorio puede ser un poco confusa porque este es un tema en lugar de un sitio web. En la práctica, todo lo que se encuentra debajo de exampleSite/
debe estar debajo del directorio raíz de un sitio web, y el directorio hugo-xmin/
de nivel superior debe estar bajo el directorio themes/
de este sitio web, i.e.,
El sitio de ejemplo proporciona una muestra config.toml
, una página de inicio _index.md
, una página sobre about.md
, dos publicaciones bajo note/
y dos bajo post/
. También anula el foot_custom.html
en el tema.
2.5.2 Implementando más funciones
El XMin es en realidad un tema altamente funcional, pero entendemos que puede ser demasiado mínimo para usted. Hay algunas características comúnmente utilizadas (intencionalmente) que faltan en este tema, y le enseñaremos cómo agregarlas usted mismo si así lo desea. Todas estas características y el código fuente se pueden aplicar también a otros temas.
Activar Google Analytics. Hugo ha proporcionado una plantilla parcial. Para XMin, puede agregar
a
layouts/partials/foot_custom.html
bajo el directorio raiz de su sitio web (en lugar dethemes/hugo-xmin/
), y configurargoogleAnalytics
en elconfig.toml
. Vea https://github.com/yihui/hugo-xmin/pull/3 para detalles, y la fuente HTML de esta página para el JavaScript renderizado desde la plantilla: https://deploy-preview-3--hugo-xmin.netlify.com.Activar comentarios Disqus. Similar a Google Analytics, puedes agregar la plantilla incorporada
a
foot_custom.html
, y configurar el nombre corto Disqus enconfig.toml
. Vea https://github.com/yihui/hugo-xmin/pull/4 para detalles, y una vista previa en https://deploy-preview-4--hugo-xmin.netlify.com.Configurar sintaxis resaltada mediante highlight.js. Agregue esto a
head_custom.html
and this to
foot_custom.html
:<script src="//YOUR-CDN-LINK/highlight.min.js"></script> <script src="//YOUR-CDN-LINK/languages/r.min.js"></script> <script> hljs.configure({languages: []}); hljs.initHighlightingOnLoad(); </script>
Recuerde reemplazar
YOUR-CDN-LINK
con el enlace al host de CDN preferido de highlight.js, por ejemplo,cdn.bootcss.com/highlight.js/9.12.0
. Para obtener más información sobre highlight.js, consulte su página principal: https://highlightjs.org. Si necesita usar otros hosts CDN, cdnjs.com es una buena opción: https://cdnjs.com/libraries/highlight.js. También puede ver qué idiomas y temas CSS son compatibles allí.Puede ver https://github.com/yihui/hugo-xmin/pull/5 para una implementación real, y una página de muestra con resaltado de sintaxis en https://deploy-preview-5--hugo-xmin.netlify.com/post/2016/02/14/a-plain-markdown-post/.
Soporte para expresiones matemáticas a través de MathJax. Agregue el código de abajo a
foot_custom.html
.<script src="//yihui.name/js/math-code.js"></script> <script async src="//cdn.bootcss.com/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"> </script>
Esto requiere un conocimiento sustancial de JavaScript y la familiaridad con MathJax para comprender completamente el código anterior, y dejaremos la explicación del código en la sección B.3.
Tenga en cuenta que bootcss.com es solo un posible servidor CDN de MathJax, y usted es libre de usar otros hosts.
Mostrar la tabla de contenidos (TOC). Para mostrar una TOC para las publicaciones R Markdown, solo necesita agregar el formato de salida
blogdown::html_page
con la opcióntoc: true
al YAML:Para las publicaciones simples de Markdown, debe modificar la plantilla
single.html
. La TOC de una publicación se almacena en la variable de plantilla Hugo.TableOfContents
. Es posible que desee una opción para controlar si mostrar la TOC, por ejemplo, puede agregar una opcióntoc: true
a los metadatos YAML de una publicación de marcado para mostrar la TOC. El código a continuación se puede agregar antes del contenido de una publicación ensingle.html
:Vea https://github.com/yihui/hugo-xmin/pull/7 para una implementación con ejemplos.
Mostrar categorías y etiquetas en una publicación si se proporciona en su YAML. Agregue el código de abajo donde usted quiera ubicar las categorías y etiquetas en
single.html
, e.g., en<div class="article-meta"></div>
.<p class="terms"> {{ range $i := (slice "categories" "tags") }} {{ with ($.Param $i) }} {{ $i | title }}: {{ range $k := . }} <a href='{{ relURL (print "/" $i "/" $k | urlize) }}'>{{$k}}</a> {{ end }} {{ end }} {{ end }} </p>
Básicamente, el código recorre los campos de metadatos de YAML
categories
ytags
, y para cada campo, su valor se obtiene de.Param
, luego usamos un bucle interno para escribir los términos con enlaces de la forma<a href="/tags/foo/">foo</a>
.Puede ver https://github.com/yihui/hugo-xmin/pull/2 para la implementación completa y una previsualización en https://deploy-preview-2--hugo-xmin.netlify.com/post/2016/02/14/a-plain-markdown-post/.
Agregar paginación. Cuando tiene una gran cantidad de publicaciones en un sitio web, es posible que no desee mostrar la lista completa en una sola página, pero muestre N publicaciones (por ejemplo, N = 10) por página. Es fácil agregar paginación a un sitio web usando las funciones y plantillas integradas de Hugo. En lugar de recorrer todas las publicaciones en una plantilla de lista (por ejemplo,
range .Data.Pages
), pagine la lista completa de publicaciones usando la función.Paginate
(por ejemplo,range (.Paginate .Data.Pages)
). A continuación se muestra un fragmento de plantilla que puede insertar en su archivo de plantillalist.html
:<ul> {{ $paginator := .Paginate .Data.Pages }} {{ range $paginator.Pages }} <li> <span class="date">{{ .Date.Format "2006/01/02" }}</span> <a href="{{ .URL }}">{{ .Title }}</a> </li> {{ end }} </ul> {{ template "_internal/pagination.html" . }}
See https://github.com/yihui/hugo-xmin/pull/16 for a full implementation.
Agregar un botón de edición de GitHub o un link a una página. Si ninguna de las características anteriores le parece emocionante (lo que no me sorprendería), esta pequeña característica es realmente un gran ejemplo de mostrarle el poder de los archivos de texto sin formato y los sitios web estáticos, cuando se combina con GitHub (u otros servicios que admiten la edición en línea de archivos de texto sin formato). Creo que sería difícil, si no imposible, implementar esta característica en marcos de sitios web dinámicos como WordPress.
Básicamente, cuando navega por cualquier archivo de texto en un repositorio en GitHub, puede editarlos directamente en la página presionando el botón Editar (mire la figura @ref(fig: github-edit) para ver un ejemplo) si tiene una cuenta de GitHub. Si tiene acceso de escritura al repositorio, puede confirmar los cambios directamente en línea, de lo contrario, GitHub bifurca automáticamente el repositorio para que pueda editar el archivo en su propio repositorio, y GitHub lo guiará para crear un pull request al repositorio original. Cuando el propietario original ve el pull request, puede ver los cambios que ha realizado y decidir si los acepta o no, o le pide que haga más cambios. Aunque la terminología “pull request” es muy confusa para los principiantes,25. Es probablemente la característica más importante inventada por GitHub, porque hace que sea mucho más fácil para las personas hacer contribuciones.
Lo que realmente es útil es que todo lo que necesita es una URL de forma fija para editar un archivo en GitHub:
https://github.com/USER/REPO/edit/BRANCH/PATH/TO/FILE
. Por ejemplo, https://github.com/rbind/yihui/edit/master/content/knitr/faq.md, dondeUSER
esrbind
,REPO
esyihui
,BRANCH
esmaster
, y la ruta del archivo escontent/knitr/faq.md
.La clave para implementar esta característica es la variable
.File.Path
, que nos da la ruta del archivo fuente de una página bajocontent/
, por ejemplo,post/foo.md
. Si su sitio web solo utiliza archivos de Markdown simples, la implementación será muy simple. Omití la URL completa de GitHub en...
a continuación, de la cual un ejemplo podría serhttps://github.com/rbind/yihui/edit/master/content/
.Sin embargo, el caso es un poco más complicado para los usuarios de blogdown, cuando se trata de publicaciones de R Markdown. No se puede usar
.File.Path
porque apunta al archivo de salida.html
de un archivo.Rmd
, mientras que el archivo.Rmd
es el archivo fuente real. El botón o enlace Edit no debe apuntar al archivo.html
. A continuación se muestra la implementación completa que puede agregar a un archivo de plantilla dependiendo de dónde desee mostrar el enlace Edit (por ejemplo,footer.html
):{{ if .File.Path }} {{ $Rmd := (print .File.BaseFileName ".Rmd") }} {{ if (where (readDir (print "content/" .File.Dir)) "Name" $Rmd) }} {{ $.Scratch.Set "FilePath" (print .File.Dir $Rmd) }} {{ else }} {{ $.Scratch.Set "FilePath" .File.Path }} {{ end }} {{ with .Site.Params.GithubEdit}} <a href='{{ . }}{{ $.Scratch.Get "FilePath" }}'>Edit this page</a> {{ end }} {{ end }}
La lógica básica es que, para un archivo, si existe el mismo nombre de archivo con la extensión
.Rmd
, señalaremos el enlace Edit al archivo Rmd. Primero, definimos una variable$ Rmd
para que sea el nombre de archivo con la extensión.Rmd
. Luego verificamos si existe. Desafortunadamente, no hay ninguna función en Hugo comofile.exists()
en R, así que tenemos que usar un truco: liste todos los archivos bajo el directorio y vea si el archivo Rmd está en la lista.$ .Scratch
es la forma de almacenar dinámicamente y obtener variables en las plantillas de Hugo. La mayoría de las variables en Hugo son de solo lectura, y usted tiene que usar$.Scratch
cuando quiera modificar una variable. Establecemos una variableFilePath
en$.Scratch
, cuyo valor es la ruta completa al archivo Rmd cuando existe el archivo Rmd, y la ruta al archivo fuente de Markdown de lo contrario. Finalmente, concatenamos una opción personalizadaGithubEdit
enconfig.toml
con la ruta del archivo para completar el enlace Edit<a>
. Aquí hay un ejemplo de la opción enconfig.toml
:Tenga en cuenta que si utiliza Hugo en Windows para compilar e implementar su sitio, es posible que tenga que cambiar los separadores de ruta de archivos de las barras diagonales inversas a barras diagonales, por ejemplo, puede necesitar
{{$.Scratch.Set "FilePath" (replace ($.Scratch.Get"FilePath") "\\" "/")}}
en la plantilla. Para evitar esta complicación, no recomendamos que implemente su sitio a través de Windows (consulte el capítulo ?? para conocer los métodos de implementación).Puede ver https://github.com/yihui/hugo-xmin/pull/6 para una implementación real con ejemplos de R Markdown, y ver el pie de página de esta página para el enlace Edit: https://deploy-preview-6--hugo-xmin.netlify.com. En realidad, puede ver un enlace en el pie de página de cada página, excepto las listas de páginas (porque no tienen archivos fuente).

FIGURA 2.3: Editar un archivo de texto en línea en GitHub.
Después de digerir el tema XMin y las implementaciones de funciones adicionales, debería ser mucho más fácil entender las plantillas de otras personas. Hay una gran cantidad de temas de Hugo, pero las principales diferencias entre ellos suelen ser estilos. Los componentes básicos de las plantillas son a menudo similares.