Mapeamento de componentes do AEM Sites
O artigo fala sobre os vários aspectos do mapeamento de componentes para sites do AEM (usando o mapeamento de componentes compostos).
Regras de mapeamento de componentes
Use uma matriz JSON de regras (seu componentmapping.json) para converter o HTML em componentes. Mantenha as regras o mais simples, explícitas e específicas possível.
Direcionar o elemento HTML e sua classe
-
Escreva o nome da marca HTML em
name. -
Inclua a classe CSS aplicada nesse elemento em
class, se a classe existir.
Exemplo:code language-html <div class ="sample-class"> <p> Sample html element </p> </div>code language-json { "name": "div", "class": "sample-class", "resourceType": "guides-components/components/table", "attributeMap": [] }
Ao definir os elementos acima, verifique o seguinte:
namepode ser uma lista separada por vírgulas (por exemplo,"h1, h2").classdeve estar presente no elemento (todas as classes listadas devem corresponder).resourceTypeindica que você pretende usar o componentetable. O pacoteguides-componentsé um OOTB fornecido pelos Guias. Você também pode usar outros pacotes de componentes, comocore/wcm/, conforme necessário.
Use attributeMap para salvar propriedades no nó JCR
Adicione entradas a attributeMap para definir propriedades no nó de saída. Cada entrada produz attrs[to] = value.
Padrões comuns:
// copy an attribute
{ "attribute": "src", "to": "image-src" }
// read content or tag name
{ "from": "textContent", "to": "jcr:title" }
{ "from": "outerHTML", "to": "text" }
{ "from": "innerHTML", "to": "text" }
{ "from": "name", "to": "type" } // the tag name, e.g., "h2"
// constant value
{ "value": true, "to": "textIsRich" }
Veja abaixo um exemplo de HTML para JSON para um elemento de imagem.
<img src="/content/dam/aemg-docs/tragopan.svg" class="cmp-image__image" itemprop="contentUrl" data-cmp-hook-image="image" alt="">
{
"name": "img",
"resourceType": "core/wcm/components/image/v2/image",
"attributeMap": [
{
"from": "src",
"to": "fileReference"
},
{
"value": ["fileReference"],
"to": "path-attributes"
}
]
}
Normalizar caminhos por meio de uma entrada dedicada
Se você quiser normalizar (tornar absoluto) valores, declare quais chaves de atributo devem ser normalizadas usando:
{
"value": ["text"],
"to": "path-attributes"
}
Cuidar dos seguintes pontos importantes:
- Coloque a lista de nomes de propriedades que você deseja normalizar em
value(por exemplo,["text"]ou["href", "src"]). - O sistema normalizará quaisquer valores encontrados nesses nomes de propriedade ao criar o componente final.
Extrair valores do HTML antes de dividir em componentes
Use from para especificar como ler um valor do elemento antes que o documento seja dividido em componentes separados:
"textContent": texto sem formatação do elemento"outerHTML": o elemento e sua marcação interna"innerHTML": somente marcação interna do elemento- Qualquer outra cadeia de caracteres: tratada como um nome de atributo (por exemplo,
"src","href")
Exemplos:
{ "from": "textContent", "to": "jcr:title" }
{ "from": "outerHTML", "to": "text" }
{ "from": "innerHTML", "to": "snippet" }
{ "from": "src", "to": "image#src" }
Exemplo completo mínimo em componentmapping.json
[
{
"name": "h1, h2",
"class": "topic-title",
"resourceType": "core/wcm/components/title/v2/title",
"attributeMap": [
{ "from": "textContent", "to": "text" },
{ "from": "name", "to": "type" }
]
},
{
"name": "img",
"class": "hero",
"resourceType": "weretail/components/content/heroimage",
"attributeMap": [
{ "from": "src", "to": "image#src" },
{ "value": ["image#src"], "to": "path-attributes" }
]
},
{
"name": "#element",
"resourceType": "core/wcm/components/text/v2/text",
"attributeMap": [
{ "from": "outerHTML", "to": "text" },
{ "value": true, "to": "textIsRich" }
]
}
]
Defina o elemento e a classe como destino, use attributeMap para definir as propriedades do nó, adicione uma entrada path-attributes para normalizar caminhos e escolha a from correta para os valores que deseja extrair. O heroimage usado acima é um componente em um site we-retail.
Observação: é importante discutir o rich text padrão e identificar os elementos para os quais ele é utilizado.
Criar um componente personalizado
Saiba como criar um componente de tabela personalizado que exibe imagens em suas células. Essa abordagem garante um design limpo e reutilizável para conteúdo dinâmico. Ele aborda o que você vai criar, por que ele é eficaz, os principais pré-requisitos, design de alto nível e muito mais.
O que você vai criar
Um componente de tabela personalizado que aceita o conteúdo de tabela do HTML e substitui cada <img> dentro dele pela saída do componente de imagem principal do AEM. Isso permite reutilizar os recursos da Imagem principal (imagens responsivas, tratamento alternativo, acessibilidade), mantendo o controle total sobre a marcação da tabela.
Usando essa abordagem, você pode criar outros componentes personalizados para seu site do AEM (usando o mapeamento de componentes compostos).
Por que essa abordagem
- Reutilizar: aproveite o comportamento maduro da imagem principal em vez de reimplementá-la.
- Consistência: as imagens na tabela se comportam da mesma forma que as imagens em qualquer outro lugar do site.
- Lado do servidor: imagens são renderizadas no servidor para desempenho, SEO e acessibilidade.
Pré-requisitos
- O AEM SDK está em execução e esse projeto está com check-out.
- Componentes principais instalados na sua instância do AEM.
- Maven disponível para build e implantação.
Design de alto nível
- O autor fornece o HTML para a tabela na caixa de diálogo do componente.
- Um Modelo Sling analisa a HTML, encontra
<img>tags e, para cada imagem, chama um serviço que renderiza o componente de Imagem principal no lado do servidor. - O modelo troca o
<img>original pela HTML de imagem principal capturada e passa o HTML concluído para o HTL para saída.
A tabela é gerada uma vez, já contendo a marcação da Imagem principal. Nenhuma manipulação de DOM do lado do cliente é necessária.
Estrutura de pastas e arquivos de chave (neste repositório)
-
HTL do componente e clientlibs:
ui.apps/src/main/content/jcr_root/apps/guides-components/components/table/table.html(renderizador HTL)_cq_editConfig.xml(atualizar ouvintes)clientlibs/comcss.txt,js.txt,css/table.css,js/table.js
-
Modelo do Sling:
core/src/main/java/com/adobe/guides/aem/components/core/models/TableModel.java -
Serviço de renderização de imagem:
core/src/main/java/com/adobe/guides/aem/components/core/services/ImageComponentRenderer.java
Etapas de implementação
Definir o componente Tabela (nó do componente)
Criar o componente em apps/guides-components/components/table. Se você ainda não tiver um, adicione um mínimo de .content.xml como abaixo para registrá-lo no painel lateral.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="Table"
componentGroup="Guides - Custom"/>
Indica ao AEM que este é um componente disponível para os autores adicionarem às páginas.
Renderizar com HTL e incluir estilos
Use um modelo Sling e gere a saída do HTML processado. Inclua a categoria clientlib para CSS/JS.
<sly data-sly-use.model="com.adobe.guides.aem.components.core.models.TableModel"
data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html">
</sly>
<sly data-sly-call="${clientLib.css @ categories='guides-components.table'}"></sly>
<sly data-sly-test="${wcmmode.edit && !model.hasContent}">
<div class="cq-placeholder" data-emptytext="${component.title}"></div>
</sly>
<div data-sly-test="${model.hasContent}"
class="gu-table-wrapper ${model.enableResponsive ? 'gu-table--responsive' : ''} gu-table--style-${model.tableStyle}"
id="${model.componentId}">
${model.processedTableHtml @ context='unsafe'}
</div>
O modelo retorna o HTML completo com a imagem principal já renderizada, portanto, o HTL apenas a imprime.
Adicionar o Modelo do Sling para processar o HTML e renderizar a Imagem principal
O modelo lê campos de diálogo, analisa a tabela HTML, encontra cada <img> e o substitui pela Imagem principal HTML por um serviço.
A seguir estão alguns dos conhecimentos importantes sobre TableModel:
- Lê
tableHtml,enableResponsive,tableStyledas propriedades do recurso. - Usa o JSoup para analisar e editar o HTML com segurança.
- Chama
ImageComponentRendererpara renderizar a Imagem principal e capturar a HTML. - Preserva as classes e o estilo CSS do
<img>original. - Normaliza caminhos DAM (remove
/jcr:content/renditions/*).
@Model(adaptables = {Resource.class, SlingHttpServletRequest.class},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class TableModel {
@ValueMapValue private String tableHtml;
@ValueMapValue private boolean enableResponsive;
@ValueMapValue private String tableStyle;
@OSGiService private ImageComponentRenderer imageRenderer;
// ...
@PostConstruct
protected void init() {
// parse HTML, for each <img> build image props (fileReference, alt, title)
// call imageRenderer.renderImageComponent(...)
// replace <img> with returned Core Image HTML
}
public String getProcessedTableHtml() { /* return final HTML */ }
}
Isso centraliza a lógica no servidor e reutiliza o comportamento da Imagem principal.
Renderizar Imagem Principal por meio de um serviço (inclusão no lado do servidor)
ImageComponentRenderer renderiza o componente de Imagem principal e captura a saída. É
- envolve um recurso que força
core/wcm/components/image/v2/image. - usa
RequestDispatcher#includepara renderizá-lo. - captura a resposta como uma cadeia de caracteres.
@Component(service = ImageComponentRenderer.class)
public class ImageComponentRenderer {
private static final String IMAGE_RESOURCE_TYPE = "core/wcm/components/image/v2/image";
public String renderImageComponent(Resource base, Map<String,Object> props,
SlingHttpServletRequest req, SlingHttpServletResponse resp) {
// create wrapped resource with IMAGE_RESOURCE_TYPE and props
// dispatcher.include(...) with a response wrapper to capture HTML
// return captured HTML
}
}
Isso permite que você insira a Imagem principal onde for necessário, não apenas como um componente secundário.
Bibliotecas de clientes
Crie uma clientlib para estilos pequenos ou JS futuro. O HTL acima carrega a categoria guides-components.table.
clientlibs/css.txt
#base=css
table.css
clientlibs/js.txt
#base=js
table.js
Isso mantém os estilos/scripts modulares e detectáveis.
Campos de diálogo (entradas do autor)
Adicione uma caixa de diálogo com pelo menos estas propriedades:
- HTML de tabela:
./tableHtml(textarea); o HTML da tabela. - Habilitar responsivo:
./enableResponsive(caixa de seleção); alterna uma classe de wrapper responsivo. - Estilo de tabela:
./tableStyle(select); aplica uma classe modificadora de estilo.
Eles mapeiam 1:1 para as propriedades do Modelo Sling e controlam a renderização.
Permitir o componente em modelos
No Editor de Modelo, edite a política de Contêiner de Layout > Componentes Permitidos > habilite o componente Tabela em Guias - Personalizado.
Os Autores não podem adicionar componentes até que as políticas os permitam.
Dicas de criação
- Colar HTML válido para a tabela. O modelo limpa e ajusta URLs de imagem.
- Usar caminhos de ativos DAM para imagens; as representações são normalizadas para o caminho do ativo original.
- Forneça texto alternativo na HTML quando possível; caso contrário, as imagens serão marcadas como decorativas.
Restrições
- O serviço força a Imagem principal v2. Para alternar versões, atualize
IMAGE_RESOURCE_TYPE. - Para renderização sintética, o modelo substitui as
.coreimg.URLs geradas pela Imagem principal por caminhos diretos do DAM e removesrcsetpara evitar URLs com falha. - Todas as renderizações ocorrem uma vez no servidor; o JavaScript é opcional.
Referência rápida (implementação)
- HTML:
ui.apps/.../components/table/table.html - Clientlibs:
ui.apps/.../components/table/clientlibs/ - Modelo:
core/.../models/TableModel.java - Serviço:
core/.../services/ImageComponentRenderer.java
Este padrão mostra como compor um componente personalizado com um Componente principal do lado do servidor, mantendo sua marcação ao reutilizar a lógica Principal.