Esta es una herramienta CLI que extrae datos de Contentful CMS y los convierte en archivos Markdown o YAML para usarlos con un generador de sitios estáticos. Se puede usar con cualquier generador de sitios estáticos que use Markdown con frontmatter YAML, pero tiene algunas características que son específicas de Hugo. También incluye un servidor Express simple que puede recibir webhooks de Contentful para reactivar comandos de obtención y eliminación (útil cuando se ejecuta un entorno de vista previa).
Instale Node.js (la versión mínima admitida es Node v18)
con el MNP
# local install
npm install contentful-hugo
# global install
npm install contentful-hugo -g
con PNPM
# local install
pnpm install contentful-hugo
# global install
pnpm install contentful-hugo -g
Complete la configuración y luego ejecute los siguientes comandos en la terminal
# # initialize the directory
contentful - hugo -- init
# # fetch content from contentful
contentful - hugo [ flags ]
npx contentful - hugo -- init
npx contentful - hugo [ flags ]
# or when using pnpm
pnpm contentful - hugo -- init
pnpm contentful - hugo [ flags ]
bandera | alias | descripción |
---|---|---|
--inicio | Inicialice el directorio. Genera un archivo de configuración y códigos cortos predeterminados para campos de texto enriquecido con contenido | |
--avance | -PAG | Se ejecuta en modo de vista previa, que extrae entradas publicadas y no publicadas de Contentful |
--esperar | -W | Espere la cantidad especificada de milisegundos antes de extraer datos de Contentful. |
--config | -DO | Especifique la ruta a un archivo de configuración. |
--servidor | -S | Ejecute en modo servidor para recibir webhooks de Contentful |
--puerto | Especificar puerto para el modo servidor (predeterminado 1414) | |
--limpio | Elimine cualquier directorio especificado en singleTypes y repetibleTypes | |
--ayuda | Mostrar ayuda | |
--versión | Mostrar número de versión |
contentful - hugo -- wait = 2000 -- preview -- config = " my_custom_config.js "
# or
contentful - hugo -- wait 2000 -- preview -- config my_custom_config.js
{
"name" : " my-hugo-project " ,
"scripts" : {
"dev" : " contentful-hugo --preview && hugo server " ,
"build" : " contentful-hugo && hugo --minify "
}
}
En este ejemplo, cuando ejecuta npm run dev
primero usará contentful-hugo para extraer datos de Contentful y luego iniciará el servidor hugo. De la misma manera, cuando ejecuta el comando npm run build
, primero usará contentful-hugo para extraer datos de Contentful y luego ejecutará hugo --minify
para crear una versión minimizada de su sitio hugo.
Intentar utilizar este paquete antes de completar la configuración devolverá un error en la consola
Error: There is an error in your config file, or it does ' t exits.
Check your config for errors or run "contentful-hugo --init" to create a config file.
De forma predeterminada, esta biblioteca buscará las siguientes variables de entorno. También puede anular estos valores con el archivo de configuración. (Ver configuración)
Archivo .env:
Para declarar estas variables de entorno, cree un archivo .env
en el directorio raíz de su proyecto.
CONTENTFUL_SPACE = ' <space-id> '
CONTENTFUL_TOKEN = ' <content-accessToken> '
# optional but required for preview mode
CONTENTFUL_PREVIEW_TOKEN = ' <preview-accessToken> '
También puede declarar las variables de entorno en la línea de comando.
Powershell:
$ env: CONTENTFUL_SPACE = " <contentful_space_id> "
$ env: CONTENTFUL_TOKEN = " <contentful_acessToken> "
$ env: CONTENTFUL_PREVIEW_TOKEN = " <contentful_preview_accessToken> "
Intento:
export CONTENTFUL_SPACE= " <contentful_space_id> "
export CONTENTFUL_TOKEN= " <contentful_accessToken> "
export CONTENTFUL_PREVIEW_TOKEN= " <contentful_preview_accessToken> "
Antes de comenzar, deberá crear un archivo de configuración en la raíz de su repositorio. Contentful-hugo buscará de forma predeterminada los siguientes archivos como configuración.
contentful-hugo.config.ts
contentful-hugo.config.js
contentful-hugo.config.yaml
contentful-hugo.yaml
contentful-settings.yaml
También puede especificar un archivo de configuración personalizado usando el indicador --config
. (Los archivos de configuración Javascript o YAML son los únicos tipos de archivos aceptados actualmente)
import { defineConfig } from 'contentful-hugo' ;
export default defineConfig ( {
// fetches from default locale if left blank
locales : [ 'en-US' , 'fr-FR' ] ,
contentful : {
// defaults to CONTENTFUL_SPACE env variable
space : 'space-id' ,
// defaults to CONTENTFUL_TOKEN env variable
token : 'content-deliver-token' ,
// defaults to CONTENTFUL_PREVIEW_TOKEN env variable
previewToken : 'content-preview-token' ,
// defaults to "master"
environment : 'master' ,
} ,
singleTypes : [
{
id : 'homepage' ,
directory : 'content' ,
fileName : '_index' ,
} ,
{
id : 'siteSettings' ,
directory : 'data' ,
fileName : 'settings' ,
fileExtension : 'yaml' , // default is md
} ,
] ,
repeatableTypes : [
{
id : 'posts' ,
directory : 'content/posts' ,
mainContent : 'content' ,
resolveEntries : {
categories : 'fields.slug' ,
author : 'fields.name' ,
relatedPosts : 'sys.id' ,
} ,
} ,
{
id : 'seoFields' ,
isHeadless : true ,
directory : 'content/seo-fields' ,
customFields : {
// these fields will be added to the frontmatter
myCustomField : 'myCustomFieldVal' ,
myOtherCustomField : ( entry ) => {
return entry . fields . whatever ;
} ,
} ,
} ,
{
id : 'reviews' ,
directory : 'content/reviews' ,
mainContent : 'reviewBody' ,
} ,
{
id : 'category' ,
directory : 'content/categories' ,
isTaxonomy : true ,
} ,
] ,
staticContent : [
{
inputDir : 'static_content' ,
outputDir : 'content' ,
} ,
] ,
} ) ;
Una configuración de JavaScript es prácticamente lo mismo que una configuración de TypeScript.
import { defineConfig } from 'contentful-hugo' ;
export default defineConfig ( {
// stuff goes here
} ) ;
La sintaxis de CommonJS también debería funcionar (en realidad no pruebo esto, tal vez funcione, tal vez no)
const { defineConfig } = require ( 'contentful-hugo' ) ;
module . exports = defineConfig ( {
// stuff goes here
} ) ;
# contentful-hugo.config.yaml
locales : # fetches from default locale if left blank
- en-US
- fr-FR
contentful :
space : ' space-id ' # defaults to CONTENTFUL_SPACE env variable
token : ' content-deliver-token ' # defaults to CONTENTFUL_TOKEN env variable
previewToken : ' content-preview-token ' # defaults to CONTENTFUL_PREVIEW_TOKEN env variable
environment : ' master ' # defaults to "master"
singleTypes :
# fetches only the most recently updated entry in a particular content type
# Generated file will be named after the fileName setting
- id : homepage
directory : content
fileName : _index
- id : siteSettings
directory : data
fileName : settings
fileExtension : yaml # default is md
repeatableTypes :
# fetches all the entries of a content type and places them in a directory.
# Generated files will be named after their Entry ID in Contentful.
- id : posts
directory : content/posts
fileExtension : md
mainContent : content
resolveEntries : # resolves a reference or asset field to a specific property
categories : fields.slug
author : fields.name
relatedPosts : sys.id
- id : seoFields
isHeadless : true
directory : content/seo-fields
customFields :
# will be added to the frontmatter
myCustomFields : ' myCustomFieldValue '
- id : reviews
directory : content/reviews
mainContent : reviewBody
- id : staff
isHeadless : true
directory : content/staff
- id : category
directory : content/categories
isTaxonomy : true
campo | requerido | descripción |
---|---|---|
espacio | opcional | ID de espacio con contenido (el valor predeterminado es la variable de entorno CONTENTFUL_SPACE si no está configurada) |
simbólico | opcional | Token de entrega de contenido (el valor predeterminado es la variable de entorno CONTENTFUL_TOKEN si no está configurada) |
token de vista previa | opcional | Token de vista previa de contenido (el valor predeterminado es la variable de entorno CONTENTFUL_PREVIEW_TOKEN si no está configurada) |
ambiente | opcional | ID de entorno con contenido (el valor predeterminado es "maestro" si no está configurado) |
campo | requerido | descripción |
---|---|---|
identificación | requerido | ID de tipo de contenido con contenido |
directorio | requerido | Directorio donde desea que se generen los archivos |
Nombre del archivo | requerido | Nombre del archivo generado |
extensión de archivo | opcional | Puede ser "md", "yml", "yaml" o "json" (el valor predeterminado es "md") |
contenido principal | opcional | ID de campo para el campo que desea que sea el contenido principal de Markdown. (Puede ser un campo de rebajas, texto enriquecido o cadena) |
tipo | opcional | Establezca manualmente el valor para el campo "tipo" en la portada (consulte los documentos de hugo) |
resolverEntradas | opcional | Resuelva los campos de referencia y/o campos de activos especificados en uno de sus parámetros de propiedades |
anula | opcional | Realizar anulaciones personalizadas para valores de campo o nombres de campo |
filtros | opcional | Acepta un objeto de parámetros de búsqueda con contenido para filtrar los resultados. Ver documentos completos |
ignorar configuraciones regionales | opcional | Ignore la configuración de localización y extraiga únicamente la configuración regional predeterminada (el valor predeterminado es falso) |
campos personalizados | opcional | Acepta un objeto de campos y valores. Los valores pueden ser un valor estático estándar o una función que acepte la entrada Contentful como parámetro y devuelva un valor. |
campo | requerido | descripción |
---|---|---|
identificación | requerido | ID de tipo de contenido con contenido |
directorio | requerido | Directorio donde desea que se generen los archivos |
Nombre del archivo | opcional | Propiedad de entrada que indicará el nombre del archivo. (Por defecto será sys.id ) |
extensión de archivo | opcional | Puede ser "md", "yml", "yaml" o "json" (el valor predeterminado es "md") |
es sin cabeza | opcional | Convierte todas las entradas de un tipo de contenido en paquetes de hojas sin cabeza (consulte los documentos de hugo). No se puede establecer en verdadero cuando isTaxonomy está establecido en verdadero. |
esTaxonomía (Experimental) | opcional | Organice las entradas en una estructura de archivos que permita metadatos de taxonomía personalizados (consulte los documentos de hugo). No se puede establecer en verdadero cuando isHeadless está establecido en verdadero. |
contenido principal | opcional | ID de campo para el campo que desea que sea el contenido principal de rebajas. (Puede ser un campo de rebajas, texto enriquecido o cadena) |
tipo | opcional | Establezca manualmente el valor para el campo "tipo" en la portada (consulte los documentos de hugo) |
resolverEntradas | opcional | Resolver los campos de referencia especificados y/o campos de activos en una de sus propiedades |
anula | opcional | Realizar anulaciones personalizadas para valores de campo o nombres de campo |
filtros | opcional | Acepta un objeto de parámetros de búsqueda con contenido para filtrar los resultados. Ver documentos completos |
ignorar configuraciones regionales | opcional | Ignore la configuración de localización y extraiga únicamente la configuración regional predeterminada (el valor predeterminado es falso) |
campos personalizados | opcional | Acepta un objeto de campos y valores. Los valores pueden ser un valor estático estándar o una función que acepte la entrada Contentful como parámetro y devuelva un valor. |
La configuración también tiene un campo de locales
que le permite especificar de qué configuraciones regionales desea extraer. Este campo puede tomar una serie de cadenas, una serie de objetos o una combinación.
De forma predeterminada, se utilizarán extensiones de archivo específicas de la configuración regional para múltiples traducciones.
const { defineConfig } = require ( 'contentful-hugo' ) ;
// produce en-us.md and fr-fr.md files
module . exports = defineConfig ( {
locales : [ 'en-US' , 'fr-FR' ] ;
// rest of config
} )
// produce en.md and fr.md files
module . exports = defineConfig ( {
locales : [
{
code : 'en-US' ,
mapTo : 'en'
} ,
{
code : 'fr-FR' ,
mapTo : 'fr'
}
]
// rest of config
} )
// produce en-us.md files and fr.md files
module . exports = defineConfig ( {
locales : [
'en-US' ,
{
code : 'fr-FR' ,
mapTo : 'fr'
}
]
// rest of config
} )
Después de configurar las configuraciones regionales en Contentful Hugo, deberá actualizar su configuración de Hugo para tener en cuenta estas configuraciones regionales. Consulte los documentos de Hugo para obtener más detalles.
# config.toml
[ languages ]
[ languages . en-us ]
# language settings
[ languages . fr-fr ]
# language settings
A veces hay casos en los que querrás colocar contenido en un directorio según su configuración regional en lugar de utilizar una traducción basada en una extensión de archivo. Para hacer esto, simplemente incluya [locale]
dentro de la ruta del archivo de su directorio.
Cuando se utilizan directorios locales específicos, las extensiones de archivo específicas de la región (es decir, en.md
o fr.md
) se eliminan.
const { defineConfig } = require ( 'contentful-hugo' ) ;
module . exports = defineConfig ( {
locales : [ 'en' , 'fr' ]
singleTypes : [
{
id : 'settings' ,
fileName : 'settings' ,
fileExtension : 'yaml' ,
directory : 'data/[locale]'
/*
produces:
- data/en/settings.yaml
- data/fr/settings.yaml
*/
}
]
repeatableTypes : [
{
id : 'post' ,
directory : 'content/[locale]/post' ,
/*
produces:
- content/en/post/[entryId].md
- content/fr/post/[entryId].md
*/
} ,
] ,
} ) ;
La configuración recomendada para Contentful Hugo es ignorar los directorios de contenido (normalmente ./content
) y datos (normalmente ./data
) en el control de versiones. Esto se debe a que contentful-hugo generará estos directorios en el momento de la compilación. Sin embargo, esto crea problemas en los casos en los que tiene páginas que no se administran en Contentful y no son generadas en el momento de la compilación por otra fuente.
Para solucionar este problema, Contentful-Hugo tiene un parámetro staticContent
. Este parámetro acepta un directorio de entrada ( inputDir
) que puede enviarse a git, y un directorio de salida ( outputDir
) que sería su directorio de datos o contenido estándar. Todos los elementos en inputDir se copiarán en outputDir en el momento de la compilación y conservarán su estructura de carpetas.abs
Por ejemplo, en la configuración siguiente, ./static_content/posts/my-post.md
se copiará en ./content/posts/my-post.md
y ./static_data/global-settings.yaml
se copiará en ./data/global-settings.yaml
.
const { defineConfig } = require ( 'contentful-hugo' ) ;
module . exports = defineConfig ( {
// rest of config
staticContent : [
{
// all items in ./static_content will be copied to ./content
inputDir : 'static_content' ,
outputDir : 'content' ,
} ,
{
// all items in ./static_data will be copied to ./data
inputDir : 'static_data' ,
outputDir : 'data' ,
} ,
] ,
} ) ;
Contentful-Hugo también observará los cambios de archivos en inputDir mientras se ejecuta en modo servidor.
A continuación se muestra un ejemplo de cómo cambiar dinámicamente las opciones token
, previewToken
y environment
según cualquier condición arbitraria.
// contentful-hugo.config.js
const { defineConfig } = require ( 'contentful-hugo' ) ;
require ( 'dotenv' ) . config ( ) ; // assuming you have "dotenv" in your dependencies
const myMasterToken = process . env . CONTENTFUL_MASTER_TOKEN ;
const myMasterPreviewToken = process . env . CONTENTFUL_MASTER_PREVIEW_TOKEN ;
const myStagingToken = process . env . CONTENTFUL_STAGING_TOKEN ;
const myStagingPreviewToken = process . env . CONTENTFUL_STAGING_PREVIEW_TOKEN ;
// set some condition
const isStaging = true || false ;
module . exports = defineConfig ( {
contentful : {
space : 'my-space-id' ,
token : isStaging ? myStagingToken : myMasterToken ,
preview : isStaging ? myStagingPreviewToken : myMasterPreviewToken ,
environment : isStaging ? 'staging' : 'master' ,
} ,
// rest of config
} ) ;
const { defineConfig } = require ( 'contentful-hugo' ) ;
// contentful-hugo.config.js
module . exports = defineConfig ( {
repeatableTypes : [
{
id : "trips" ,
directory : "content/trips"
overrides : {
// change the url field name to "slug"
url : {
fieldName : "slug"
}
/*
rename "distanceInKilometers" to "distanceInMiles"
and change the field value from km to mi
*/
distanceInKilometers : {
fieldName : "distanceInMiles" , valueTransformer : ( val ) => {
if ( typeof val === 'number' ) {
return val * 0.621371
}
return 0
}
}
}
}
]
} )
// ALTERNATIVE SYNTAX
module . exports = defineConfig ( {
repeatableTypes : [
{
id : "trips" ,
directory : "content/trips"
overrides : [
{
field : "url" ,
options : {
// change the url field name to "slug" in frontmatter
fieldName : "slug"
}
} ,
{
field : "distanceInKilometers" ,
options : {
// rename "distanceInKilometers" to "distanceInMiles"
fieldName : "distanceInMiles" ,
// convert distance to miles and output the result in frontmatter
valueTransformer : ( val ) => {
if ( typeof val === 'number' ) {
return val * 0.621371
}
return 0
}
}
} ]
}
]
} )
Para archivos de configuración JS, puede utilizar el asistente defineConfig
o puede importar el tipo ContentfulHugoConfig
.
//////////// OPTION 1 ////////////
const { defineConfig } = require ( 'contentful-hugo' ) ;
module . exports = defineConfig ( {
// config goes here
} ) ;
//////////// OPTION 2 ////////////
/**
* @type {import('contentful-hugo').ContentfulHugoConfig}
*/
module . exports = {
// rest of config
} ;
Ejemplo de configuración .gitignore
# general stuff
.env
node_modules
public
resources
# Contenful Hugo stuff
# temp folder that contentful uses to track files
.contentful-hugo
# since content and data is coming from Contentful
# usually you'll want to ignore those directories
content
data
Los archivos se generarán en el directorio especificado en el archivo de configuración. La portada estará en formato YAML. Los archivos de un solo tipo recibirán el nombre del nombre de archivo especificado en el archivo de configuración. Los archivos de tipos repetibles recibirán el nombre de su ID de entrada en Contenful, lo que facilita la vinculación de archivos.
Los siguientes campos siempre aparecerán en tu frontmatter:
date : # defaults to sys.createdAt unless you have a field with the id "date" then it get's overwritten
sys :
id : # the entry id
updatedAt : # the last time this entry was updated in Contentful
createdAt : # when the entry was created in Contentful
revision : # the revision number
space : # the space id
contentType : # the content type id
Los recursos como imágenes y videos vienen con información adicional que facilita la implementación de cosas como texto alternativo o diseños que dependen del conocimiento de las dimensiones de la imagen. Los campos son los siguientes:
assetFieldName :
assetType : # indicates the asset mime type such as image/png, video/mp4, audio/mp3, ect.
url : # url of the asset
title : # title of the asset written in Contentful
description : # description of the asset written in Contentful
width : # width of the asset (images only)
height : # height of the asset (images only)
Si está utilizando Hugo, puede acceder a la información como se muestra a continuación:
< img
src =" {{ .Params.assetFieldName.url }} "
width =" {{ .Params.assetFieldName.width }} "
/>
Para las imágenes, puede agregar parámetros a la URL del activo para poder utilizar la API de imágenes de Contentful.
< img
src =" {{ .Params.assetFieldname.url }}?w=200&h=200&fit=fill "
width =" 200 "
height =" 200 "
/>
Esta misma información también aparecerá en conjuntos de activos como una galería:
myGallery :
- assetType : ' image/jpg '
url : ' //link-to-image.jpg '
title : ' Image 1 '
description : ' Image 1 Description '
width : 500
height : 500
- assetType : ' image/jpg '
url : ' //link-to-image-2.jpg '
title : ' Image 2 '
description : ' Image 2 Description '
width : 1920
height : 1080
Las entradas vinculadas incluirán campos para su identificación y su identificación del tipo de contenido.
linkedEntry :
id : <contentful-entry-id>
typeId : <content-type-ID>
# example with array of linked entries
relatedArticles :
- id : ' 41UFfIhszbS1kh95bomMj7 '
typeId : ' articles '
- id : ' 85UFfIhsacS1kh71bpqMj7 '
typeId : ' articles '
Todos los archivos llevan el nombre de su ID de entrada en Contentful, lo que facilita su recuperación usando .Site.GetPage
en Hugo.
// if you have access to the "Page" object
{{ with . Site . GetPage "<path-to-file>/<entry-id>" }}
{{ . Title }}
{{ end }}
// if you don't have access to the "Page" object
// for example in a nested partial
{{ with site. GetPage "<path-to-file>/<entry-id>" }}
{{ . Title }}
{{ end }}
Ejemplo sencillo
{{ with . Params . myEntryField }}
{{ $ pagePage := print "path/to/entryDir/" . id }}
{{ with site. GetPage $ pagePath }}
{{ . Title }}
{{ . Params . someOtherField }}
{{ end }}
{{ end }}
Documentación relevante:
Un campo de texto enriquecido configurado como "contenido principal" para un tipo de contenido se representará como rebaja para Hugo.
El contenido dinámico, como embedded-entry-blocks
se representa como códigos cortos con parámetros incluidos que se pueden utilizar para recuperar los datos necesarios.
<!-- example embedded entry -->
<!-- you can use the id, contentType, and parentContentType parameters to fetch the desired data -->
{{< contentful-hugo/embedded-entry id="nTLo2ffSJJp5QrnrO5IU9" contentType="gallery" parentContentType="post" >}}
Antes de obtener datos de texto enriquecido, asegúrese de haber ejecutado contentful-hugo --init
para tener todos los códigos cortos de texto enriquecido. Una vez que tenga estos códigos cortos, puede ampliarlos y modificarlos para adaptarlos a sus necesidades.
La lista de códigos cortos de texto enriquecido incluye:
De forma predeterminada, los códigos cortos de texto enriquecido mostrarán una notificación para un elemento no configurado.
Puedes personalizarlos navegando a layouts/shortcodes/contentful-hugo/{shortcode-name}.html
Un campo de texto enriquecido producirá matrices anidadas que reflejan la estructura JSON que tienen en la API. Será necesario recorrer cada nodo y generar HTML según el campo nodeType.
richTextField :
- nodeType : ' paragraph '
data : {}
content :
- data : {}
marks : []
value : ' This is a simple paragraph. '
nodeType : ' text '
- nodeType : ' paragraph '
data : {}
content :
- data : {}
marks : []
value : ' This is a paragraph with '
nodeType : ' text '
- data : {}
marks :
- type : ' italic '
value : ' italicized text. '
nodeType : ' text '
- nodeType : ' embedded-asset-block '
data :
assetType : ' image/jpeg '
url : ' //images.ctfassets.net/some-image-url.jpg '
title : ' Image title will appear here '
description : ' Image description will appear here '
width : 1920
height : 1080
content : []
Además, se generará una versión en texto plano del campo utilizando el ID del campo al que se le añade "_plaintext". Esto le permite recuperar rápidamente el texto por sí solo sin ningún otro dato. Un caso de uso simple sería utilizar la salida de texto sin formato para generar automáticamente una meta descripción para una página web.
richTextField_plaintext : ' This is a simple paragraph. This is a paragraph with italicized text. '
La opción de resolver entradas le permite especificar una propiedad de una entrada o activo al que se hace referencia para resolver ese valor de campo. Por ejemplo, supongamos que tiene un tipo de contenido category
al que se hace referencia en posts
. Normalmente contentful-hugo dará el siguiente resultado
category :
id : some-entry-id
contentType : category
Si bien esto facilita la búsqueda de la categoría, este formato no le permite utilizar las funciones de taxonomía integradas de Hugo. Con el parámetro resolveEntries
puedes remediar esto.
// from the config file
module . exports = defineConfig ( {
repeatableTypes : [
id : 'posts' ,
directory : 'content/posts' ,
resolveEntries : {
category : 'fields.slug'
}
// alternative syntax
resolveEntries : [
{
field : 'category' ,
resolveTo : 'fields.slug' ,
} ,
] ,
]
} )
Ahora el campo de categoría solo mostrará el slug como valor.
category : my-category-slug
La función de resolución de entradas funciona tanto con campos de referencia como con campos de activos, así como con múltiples campos de referencia y de activos.
Las anulaciones se pueden utilizar para modificar nombres de campos y valores de campos.
A continuación se muestra un ejemplo sencillo de cómo cambiar el nombre de un campo de "url" a "videoUrl".
repeatableTypes: [
{
id : 'youtubeVideo' ,
directory : 'content/_youtubeVideo' ,
isHeadless : true ,
overrides : {
// the name of the url field to videoUrl
url : {
fieldName : 'videoUrl'
}
}
// alternative syntax
overrides : [
{
field : 'url' ,
options : {
fieldName : 'videoUrl' ,
} ,
} ,
] ,
} ,
] ;
overrides
también tiene opciones valueTransformer
que le permiten manipular los datos del campo que aparecerán en el frontmatter. valueTransformer
toma un método que tiene el valor del campo como parámetro y luego devuelve el resultado final que aparecerá en el frontmatter. (Tenga en cuenta que, dado que valueTransformer
debe ser un método, esta opción solo funcionará en archivos de configuración de JavaScript)
Aquí hay un ejemplo en el que cambiamos el nombre del campo de "url" a "videoId" y luego usamos valueTransformer
para extraer la identificación del video de la URL y luego lo colocamos en el frontmatter.
repeatableTypes: [
{
id : 'youtubeVideo' ,
directory : 'content/_youtubeVideo' ,
isHeadless : true ,
overrides : {
url : {
fieldName : 'videoId' ,
// "value" is whatever value is currently saved in the field.
// in this case it's a url for a youtube video
valueTransformer : ( value ) => {
if ( ! value ) {
return null ;
}
const url = new URL ( value ) ;
// extract the video id from the url and return it
return url . searchParams . get ( 'v' ) ;
}
}
}
// alternative syntax
overrides : [
{
field : 'url' ,
options : {
fieldName : 'videoId' ,
valueTransformer : ( value ) => {
// transform the value
} ,
} ,
} ,
] ,
} ,
] ;
Cuando utilice la opción valueTransformer
en campos que contienen matrices, asegúrese de recorrer el valor al manipularlo.
repeatabledTypes: [
{
id : 'post' ,
directory : 'content/posts' ,
overrides : {
authors : {
valueTransformer : ( authorRefs ) => {
const authors = [ ] ;
for ( const ref of authorRefs ) {
// get the name, photo, and bio of the author
// and add it to the array
authors . push ( {
name : ref . fields . name ,
photo : ref . fields . photo . fields . file . url ,
bio : ref . fields . bio ,
} ) ;
}
return authors ;
} ,
} ,
} ,
} ,
] ;
Ahora el campo authors
se verá así:
authors :
- name : Some Name
photo : //images.cfassets.net/path-to-photo.jpg
bio : some bio text
- name : Some other name
photo : //images.cfassets.net/path-to-photo.jpg
bio : some other bio text
Como puede ver, esto se puede usar para producir resultados similares al parámetro resolveEntries
, pero resolveEntries
solo puede devolver una propiedad, mientras que con las anulaciones puede hacer lo que quiera con los valores de los campos.
Puede utilizar la opción filters
para ingresar parámetros de búsqueda que le permitan filtrar entradas según algunas de sus propiedades. Para obtener más información sobre los parámetros de búsqueda de contenido, visite sus documentos.
Tenga en cuenta que los siguientes parámetros de búsqueda se ignorarán content_type
, skip
, order
, limit
module . exports = defineConfig ( {
singleTypes : [
// get a homepage with a specific entryId
{
id : 'homepage' ,
directory : 'content' ,
fileName : '_index' ,
filters : {
'sys.id' : 'my-homepace-id'
}
}
]
repeatableTypes : [
// only get events that start after 01/01/2020
{
id : 'events' ,
directory : 'content/events' ,
filters : {
'fields.startDate[gte]' : '2020-01-01T00:00:00Z' ,
} ,
} ,
// get posts where author is "John Doe" and contains the tag "flowers"
{
id : 'posts' ,
directory : 'content/posts' ,
filters : {
'fields.author' : 'John Doe' ,
'fields.tags' : 'flowers'
} ,
} ,
] ;
} )
Puede utilizar el parámetro customFields
para agregar campos adicionales a sus entradas. La configuración de los campos personalizados puede ser un valor estático o un método que acepte una entrada Contentful como parámetro y devuelva un valor.
Digamos que tenemos un tipo de contenido de autor con los siguientes campos:
Aquí hay una configuración de ejemplo:
module . exports = defineConfig ( {
// rest of config
repeatableTypes : [
{
id : 'author' ,
directory : 'content/authors' ,
customFields : {
// both "myCustomField" and "fullName"
// will be appended to the frontmatter for author entries
myCustomField : 'myCustomFieldValue' ,
fullName : ( entry ) => {
const { firstName , lastName } = entry . fields ;
return ` ${ firstName } ${ lastName } ` ;
} ,
} ,
} ,
] ,
} ) ;
Esto es lo que resultará de esa configuración
---
firstName : ' John '
lastName : ' Doe '
slug : ' john-doe '
myCustomField : ' myCustomFieldValue ' # custom field
fullName : ' John Doe ' # custom field
---
También puedes usar esto para campos específicos de Hugo como Opciones de compilación.
// prevent a content type from appearing in list pages
{
customFields : {
_build : {
render : 'alway' ,
list : 'never' ,
publishResources : true
}
}
}
// prevent a content type from rendering a single page
{
customFields : {
_build : {
render : 'never' ,
list : 'always' ,
publishResources : true
}
}
}
Estos son algunos problemas conocidos.
--wait
a su secuencia de comandos. Aquí hay un ejemplo en el que esperamos 6 segundos adicionales contentful-hugo --wait=6000
.hugo server --disableFastRender