Esta é uma ferramenta CLI que extrai dados do Contentful CMS e os transforma em arquivos Markdown ou YAML para uso com um gerador de site estático. Ele pode ser usado com qualquer gerador de site estático que utilize Markdown com frontmatter YAML, mas possui alguns recursos específicos do Hugo. Ele também inclui um servidor Express simples que pode receber webhooks do Contentful para reativar comandos get e delete (útil ao executar um ambiente de visualização).
Instale o Node.js (a versão mínima suportada é Node v18)
com NPM
# local install
npm install contentful-hugo
# global install
npm install contentful-hugo -g
com PNPM
# local install
pnpm install contentful-hugo
# global install
pnpm install contentful-hugo -g
Conclua a configuração e execute os seguintes comandos no 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 ]
bandeira | apelidos | descrição |
---|---|---|
--init | Inicialize o diretório. Gera um arquivo de configuração e códigos de acesso padrão para campos rich text com conteúdo | |
--preview | -P | É executado no modo de visualização, que extrai entradas publicadas e não publicadas do Contentful |
--espere | -C | Aguarde o número especificado de milissegundos antes de extrair dados do Contentful. |
--config | -C | Especifique o caminho para um arquivo de configuração. |
--servidor | -S | Execute no modo servidor para receber webhooks do Contentful |
--porta | Especifique a porta para o modo servidor (padrão 1414) | |
--limpar | Exclua todos os diretórios especificados em singleTypes e repetibleTypes | |
--ajuda | Mostrar ajuda | |
--versão | Mostrar número da versão |
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 "
}
}
Neste exemplo, quando você executa npm run dev
ele primeiro usará contentful-hugo para extrair dados do Contentful e, em seguida, iniciará o servidor hugo. Da mesma forma, quando você executa o comando npm run build
ele primeiro usará contentful-hugo para extrair dados do Contentful e depois executará hugo --minify
para construir uma versão reduzida do seu site hugo.
Tentar usar este pacote antes de concluir a configuração retornará um erro no console
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.
Por padrão, esta biblioteca procurará as seguintes variáveis de ambiente. Você também pode substituir esses valores pelo arquivo de configuração. (Veja configuração)
Arquivo .env:
Para declarar essas variáveis de ambiente, crie um arquivo .env
no diretório raiz do seu projeto.
CONTENTFUL_SPACE = ' <space-id> '
CONTENTFUL_TOKEN = ' <content-accessToken> '
# optional but required for preview mode
CONTENTFUL_PREVIEW_TOKEN = ' <preview-accessToken> '
Você também pode declarar as variáveis de ambiente na linha de comando
Concha de energia:
$ env: CONTENTFUL_SPACE = " <contentful_space_id> "
$ env: CONTENTFUL_TOKEN = " <contentful_acessToken> "
$ env: CONTENTFUL_PREVIEW_TOKEN = " <contentful_preview_accessToken> "
Bash:
export CONTENTFUL_SPACE= " <contentful_space_id> "
export CONTENTFUL_TOKEN= " <contentful_accessToken> "
export CONTENTFUL_PREVIEW_TOKEN= " <contentful_preview_accessToken> "
Antes de começar, você precisará criar um arquivo de configuração na raiz do seu repositório. Por padrão, Contentful-hugo procurará os seguintes arquivos como uma configuração.
contentful-hugo.config.ts
contentful-hugo.config.js
contentful-hugo.config.yaml
contentful-hugo.yaml
contentful-settings.yaml
Você também pode especificar um arquivo de configuração personalizado usando o sinalizador --config
. (Arquivos de configuração Javascript ou YAML são os únicos tipos de arquivos aceitos atualmente)
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' ,
} ,
] ,
} ) ;
Uma configuração javascript é praticamente igual a uma configuração typescript.
import { defineConfig } from 'contentful-hugo' ;
export default defineConfig ( {
// stuff goes here
} ) ;
A sintaxe CommonJS também deve funcionar (na verdade, não testo isso, talvez funcione, talvez não)
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 | obrigatório | descrição |
---|---|---|
espaço | opcional | Contentful Space ID (o padrão é a variável de ambiente CONTENTFUL_SPACE se não estiver definido) |
ficha | opcional | Token de entrega de conteúdo (o padrão é a variável de ambiente CONTENTFUL_TOKEN se não estiver definido) |
visualizaçãoToken | opcional | Token de visualização de conteúdo (o padrão é a variável de ambiente CONTENTFUL_PREVIEW_TOKEN se não estiver definido) |
ambiente | opcional | ID do ambiente com conteúdo (o padrão é "master" se não estiver definido) |
campo | obrigatório | descrição |
---|---|---|
eu ia | obrigatório | ID do tipo de conteúdo com conteúdo |
diretório | obrigatório | Diretório onde você deseja que os arquivos sejam gerados |
nome do arquivo | obrigatório | Nome do arquivo gerado |
extensão de arquivo | opcional | Pode ser "md", "yml", "yaml" ou "json" (o padrão é "md") |
conteúdo principal | opcional | ID do campo que você deseja que seja o conteúdo principal do Markdown. (Pode ser um campo markdown, richtext ou string) |
tipo | opcional | Defina manualmente o valor para o campo "type" no frontmatter (veja hugo docs) |
resolverEntradas | opcional | Resolva os campos de referência e/ou campos de ativos especificados para um de seus parâmetros de propriedades |
substituições | opcional | Faça substituições personalizadas para valores ou nomes de campos |
filtros | opcional | Aceita um objeto de parâmetros de pesquisa com conteúdo para filtrar os resultados. Veja documentos com conteúdo |
ignorarLocales | opcional | Ignore as configurações de localização e extraia apenas da localidade padrão (o padrão é falso) |
campos personalizados | opcional | Aceita um objeto de campos e valores. Os valores podem ser um valor estático padrão ou uma função que aceita a entrada Contentful como parâmetro e retorna um valor |
campo | obrigatório | descrição |
---|---|---|
eu ia | obrigatório | ID do tipo de conteúdo com conteúdo |
diretório | obrigatório | Diretório onde você deseja que os arquivos sejam gerados |
nome do arquivo | opcional | Propriedade de entrada que indicará o nome do arquivo. (Por padrão, será sys.id ) |
extensão de arquivo | opcional | Pode ser "md", "yml", "yaml" ou "json" (o padrão é "md") |
é sem cabeça | opcional | Transforma todas as entradas em um tipo de conteúdo em pacotes de folhas sem cabeçalho (consulte hugo docs). Não pode ser definido como verdadeiro quando isTaxonomy está definido como verdadeiro. |
isTaxonomia (Experimental) | opcional | Organize entradas na estrutura de arquivos permitindo metadados de taxonomia personalizados (consulte hugo docs). Não pode ser definido como verdadeiro quando isHeadless estiver definido como verdadeiro. |
conteúdo principal | opcional | ID do campo que você deseja que seja o conteúdo principal do markdown. (Pode ser um campo markdown, richtext ou string) |
tipo | opcional | Defina manualmente o valor para o campo "type" no frontmatter (veja hugo docs) |
resolverEntradas | opcional | Resolva os campos de referência e/ou campos de ativos especificados para uma de suas propriedades |
substituições | opcional | Faça substituições personalizadas para valores ou nomes de campos |
filtros | opcional | Aceita um objeto de parâmetros de pesquisa com conteúdo para filtrar os resultados. Veja documentos com conteúdo |
ignorarLocales | opcional | Ignore as configurações de localização e extraia apenas da localidade padrão (o padrão é falso) |
campos personalizados | opcional | Aceita um objeto de campos e valores. Os valores podem ser um valor estático padrão ou uma função que aceita a entrada Contentful como parâmetro e retorna um valor |
A configuração também possui um campo locales
que permite especificar de quais localidades você deseja extrair. Este campo pode receber uma matriz de strings, uma matriz de objetos ou uma combinação.
Por padrão, extensões de arquivo específicas de localidade serão usadas para múltiplas traduções.
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
} )
Depois de configurar as localidades no Contentful Hugo, você precisará atualizar sua configuração do Hugo para dar conta dessas localidades. Consulte a documentação do Hugo para mais detalhes.
# config.toml
[ languages ]
[ languages . en-us ]
# language settings
[ languages . fr-fr ]
# language settings
Às vezes, há casos em que você desejará colocar o conteúdo em um diretório com base em sua localidade, em vez de usar uma tradução baseada em extensão de arquivo. Para fazer isso, basta incluir [locale]
no caminho do arquivo do diretório.
Ao usar diretórios específicos de localidade, as extensões de arquivo específicas de localidade (ou seja, en.md
ou fr.md
) são eliminadas
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
*/
} ,
] ,
} ) ;
A configuração recomendada para Contentful Hugo é ter seus diretórios de conteúdo (geralmente ./content
) e dados (geralmente ./data
) ignorados no controle de versão. Isso ocorre porque contentful-hugo irá gerar esses diretórios em tempo de construção. No entanto, isso cria problemas para casos em que você tem páginas que não são gerenciadas no Contentful e não são geradas no momento da construção por outra fonte.
Para lidar com este problema, Contentful-Hugo possui um parâmetro staticContent
. Este parâmetro aceita um diretório de entrada ( inputDir
) que pode ser confirmado no git e um diretório de saída ( outputDir
) que seria seu conteúdo padrão ou diretório de dados. Todos os itens no inputDir serão copiados para o outputDir no momento da compilação e manterão sua estrutura de pastas.abs
Por exemplo, na configuração abaixo, ./static_content/posts/my-post.md
será copiado para ./content/posts/my-post.md
e ./static_data/global-settings.yaml
será copiado para ./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 também observará alterações de arquivo no inputDir enquanto estiver executando no modo servidor.
Aqui está um exemplo de alteração dinâmica das opções token
, previewToken
e environment
dependendo de qualquer condição arbitrária.
// 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 arquivos de configuração JS, você pode usar o auxiliar defineConfig
ou importar o 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
} ;
Exemplo de configuração .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
Os arquivos serão gerados no diretório especificado no arquivo de configuração. O assunto inicial estará no formato YAML. Arquivos de tipos únicos serão nomeados de acordo com fileName especificado no arquivo de configuração. Arquivos de tipos repetíveis serão nomeados de acordo com seu ID de entrada no Contenful, o que facilita a vinculação de arquivos.
Os seguintes campos sempre aparecerão no seu 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
Ativos como imagens e vídeos vêm com algumas informações extras que facilitam a implementação de coisas como texto alternativo ou layouts que dependem do conhecimento das dimensões da imagem. Os campos são os seguintes:
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)
Se você estiver usando o Hugo você pode acessar as informações abaixo:
< img
src =" {{ .Params.assetFieldName.url }} "
width =" {{ .Params.assetFieldName.width }} "
/>
Para imagens, você pode anexar parâmetros ao URL do ativo para usar a API de imagens do Contentful
< img
src =" {{ .Params.assetFieldname.url }}?w=200&h=200&fit=fill "
width =" 200 "
height =" 200 "
/>
Essas mesmas informações também aparecerão em matrizes de ativos como uma galeria:
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
As entradas vinculadas incluirão campos para seu ID e seu ID de tipo de conteúdo.
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 os arquivos são nomeados de acordo com seu ID de entrada no Contentful, facilitando sua recuperação usando .Site.GetPage
no 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 }}
Exemplo simples
{{ with . Params . myEntryField }}
{{ $ pagePage := print "path/to/entryDir/" . id }}
{{ with site. GetPage $ pagePath }}
{{ . Title }}
{{ . Params . someOtherField }}
{{ end }}
{{ end }}
Documentação Relevante:
Um campo rich text definido como "mainContent" para um tipo de conteúdo será renderizado como markdown para Hugo.
Conteúdo dinâmico, como embedded-entry-blocks
são renderizados como códigos de acesso com parâmetros incluídos que podem ser usados para buscar os dados necessários.
<!-- 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 buscar dados de rich text, certifique-se de ter executado contentful-hugo --init
para ter todos os códigos de acesso de rich text. Depois de ter esses códigos de acesso, você pode estendê-los e modificá-los para atender às suas necessidades.
A lista de códigos curtos de rich text inclui:
Por padrão, os códigos curtos de richtext mostrarão uma notificação para um item não configurado.
Você pode personalizá-los navegando até layouts/shortcodes/contentful-hugo/{shortcode-name}.html
Um campo Rich Text produzirá matrizes aninhadas que espelham a estrutura JSON que possuem na API. Cada nó precisará passar por um loop e produzir HTML dependendo do 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 : []
Além disso, uma versão em texto simples do campo será gerada usando o ID do campo anexado com "_plaintext". Isso permite que você busque rapidamente o texto sozinho, sem nenhum outro dado. Um caso de uso simples seria usar a saída de texto simples para gerar automaticamente uma meta descrição para uma página da web.
richTextField_plaintext : ' This is a simple paragraph. This is a paragraph with italicized text. '
A opção resolver entradas permite especificar uma propriedade de uma entrada ou ativo referenciado para resolver esse valor de campo. Por exemplo, digamos que você tenha um tipo de conteúdo category
referenciado em posts
. Normalmente contentful-hugo dará o seguinte resultado
category :
id : some-entry-id
contentType : category
Embora isso facilite a localização da categoria, esse formato não permite que você use os recursos de taxonomia integrados do Hugo. Com o parâmetro resolveEntries
você pode remediar isso.
// 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' ,
} ,
] ,
]
} )
Agora o campo de categoria exibirá apenas o slug como valor.
category : my-category-slug
O recurso de resolução de entradas funciona com campos de referência e campos de ativos, bem como com referências múltiplas e campos de ativos múltiplos.
As substituições podem ser usadas para modificar nomes e valores de campos.
Aqui está um exemplo simples de como alterar o nome de um campo de “url” para “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
também possui um valueTransformer
options que permite manipular os dados do campo que aparecerão no frontmatter. valueTransformer
pega um método que tem o valor do campo como parâmetro e depois retorna o resultado final que aparecerá no frontmatter. (Esteja ciente de que como valueTransformer
deve ser um método, esta opção só funcionará em arquivos de configuração javascript)
Aqui está um exemplo onde alteramos o nome do campo de "url" para "videoId" e então usamos o valueTransformer
para extrair o ID do vídeo da url e colocá-lo no 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
} ,
} ,
} ,
] ,
} ,
] ;
Ao usar a opção valueTransformer
em campos que contêm matrizes, certifique-se de percorrer o valor ao manipulá-lo.
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 ;
} ,
} ,
} ,
} ,
] ;
Agora o campo authors
ficará assim:
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 você pode ver, isso pode ser usado para produzir resultados semelhantes ao parâmetro resolveEntries
, mas resolveEntries
só pode retornar uma propriedade enquanto com substituições você pode fazer o que quiser com os valores do campo.
Você pode usar a opção filters
para inserir parâmetros de pesquisa, permitindo filtrar entradas com base em algumas de suas propriedades. Para obter mais informações sobre parâmetros de pesquisa de conteúdo, visite seus documentos.
Esteja ciente de que os seguintes parâmetros de pesquisa serão ignorados 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'
} ,
} ,
] ;
} )
Você pode usar o parâmetro customFields
para adicionar campos adicionais às suas entradas. A configuração para campos personalizados pode ser um valor estático ou um método que aceita uma entrada Contentful como parâmetro e retorna um valor.
Digamos que temos um tipo de conteúdo de autor com os seguintes campos:
Aqui está um exemplo de configuração:
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 } ` ;
} ,
} ,
} ,
] ,
} ) ;
Aqui está o que essa configuração resultará
---
firstName : ' John '
lastName : ' Doe '
slug : ' john-doe '
myCustomField : ' myCustomFieldValue ' # custom field
fullName : ' John Doe ' # custom field
---
Você também pode usar isso para campos específicos do Hugo, como Opções de construção
// 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
}
}
}
Esses são alguns problemas conhecidos.
--wait
ao seu script. Aqui está um exemplo em que esperamos mais 6 segundos contentful-hugo --wait=6000
.hugo server --disableFastRender