Noções básicas e configuração do modelo de transformação da página de publicação (a partir de uma versão de junho de 2019)

As páginas de publicação são sempre baseadas em um layout de página e uma página master. Essas duas páginas combinadas com campos contendo dados compõem a página que um usuário vê no navegador. Ao transformar páginas de publicação, é obrigatório mapear os layouts de página usados em um modelo de transformação de página de publicação. O componente de transformação da página de publicação terá um mapeamento de layout de página 'padrão' para todos os layouts de página prontos para uso, portanto, se o seu portal estiver usando esses layouts de página prontos para uso, você estará coberto. A realidade é que a maioria dos portais usa layouts de página personalizados (e páginas de master personalizadas) e, portanto, há uma necessidade de mapeamentos de layout de página para esses layouts de página personalizados. Layouts de página personalizados podem ser tratados de duas maneiras:

  • A opção preferencial é que você mesmo forneça um arquivo de mapeamento de layout de página personalizado, isso lhe dá controle total sobre quais campos são traduzidos em Web Parts e onde eles residem na página moderna, quais campos se tornam metadados e muito mais.
  • Se não for encontrado nenhum mapeamento de layout de página para a página que você está transformando, geraremos um mapeamento dinâmico e o usaremos. A desvantagem dessa abordagem é que todo o conteúdo acabará na mesma seção e coluna da página moderna.

Gerando um arquivo de mapeamento de layout de página

Se você estiver usando layouts de página personalizados, é recomendável usar um arquivo de mapeamento de layout de página personalizado para que você possa obter páginas modernas mais precisas. Felizmente, você não precisa criar manualmente esses arquivos de layout personalizados, há uma API .Net e suporte ao PowerShell PnP para gerar um.

Usando o PowerShell

Usando o cmdlet, Export-PnPPageMapping você pode:

  • Exporte o arquivo de mapeamento integrado (-BuiltInPageLayoutMapping parâmetro): este arquivo será usado para os layouts de página prontos para uso. Se você especificar um mapeamento personalizado para um layout de página pronto para uso em seu próprio arquivo de mapeamento, esse mapeamento terá preferência sobre o mapeamento OOB
  • Analise os layouts de página no portal conectado e exporte-os como um arquivo de mapeamento (-CustomPageLayoutMapping parâmetro): todos os layouts de página personalizados encontrados são analisados e exportados. Se você também deseja que seus layouts de página OOB sejam analisados, use o -AnalyzeOOBPageLayouts parâmetro.
# Connect to your "classic" portal
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/classicportal -Interactive

# Analyze and export the page layout mapping files
Export-PnPPageMapping -BuiltInPageLayoutMapping -CustomPageLayoutMapping -Folder c:\temp

Usando o .Net

No .Net, você precisa usar a classe para analisar layouts de PageLayoutAnalyser página. Abaixo, dois snippets mostram como analisar todos os layouts de página ou os layouts de página usados por determinadas páginas de publicação.

string siteUrl = "https://contoso.sharepoint.com/sites/classicportal";
AuthenticationManager am = new AuthenticationManager("<Azure AD client id>", "joe@contoso.onmicrosoft.com", "Pwd as SecureString");
using (var cc = am.GetSharePointOnlineAuthenticatedContextTenant(siteUrl))
{
    var analyzer = new PageLayoutAnalyser(cc);
    // Analyze all found page layouts
    analyzer.AnalyseAll();  
    analyzer.GenerateMappingFile("c:\\temp", "custompagelayoutmapping.xml");
}
string siteUrl = "https://contoso.sharepoint.com/sites/classicportal";
AuthenticationManager am = new AuthenticationManager("<Azure AD client id>", "joe@contoso.onmicrosoft.com", "Pwd as SecureString");
using (var cc = am.GetSharePointOnlineAuthenticatedContextTenant(siteUrl))
{
    var analyzer = new PageLayoutAnalyser(cc);
    // Analyze all the unique page layouts for publishing pages starting with an "a"
    var pages = cc.Web.GetPagesFromList("Pages", "a");
    foreach (var page in pages)
    {
        analyzer.AnalysePageLayoutFromPublishingPage(page);
    }

    analyzer.GenerateMappingFile("c:\\temp", "custompagelayoutmapping.xml");
}

O modelo de mapeamento de layout de página explicado

Quando você abre um arquivo de mapeamento de layout de página, os seguintes elementos de nível superior estão presentes:

  • Complementos: como usuário da transformação de página, você pode ter a necessidade de aplicar lógica personalizada para atender às suas necessidades, por exemplo, você precisa transformar uma determinada propriedade de uma forma que ela possa funcionar com sua web part SPFX personalizada. A estrutura suporta isso, permitindo que você adicione seus assemblies com funções ... simplesmente defini-las na seção AddOn e, em seguida, referenciar suas funções personalizadas posteriormente, prefixando-as com o nome fornecido, fará com que a transformação da página de publicação use seu código personalizado.

  • PageLayouts: esse elemento contém informações para cada layout de página que você planeja usar. Para cada layout de página, você encontrará uma definição do cabeçalho, da web part, dos metadados, das zonas da web part e das web parts fixas.

Os próximos capítulos oferecerão mais detalhes.

Definição de PageLayout no modelo de layout de página

Vamos analisar como um mapeamento de layout de página é configurado no modelo de mapeamento de layout de página, o que é melhor feito com base em uma definição de exemplo:

    <PageLayout Name="MyPageLayout" AlsoAppliesTo="MyOtherPageLayout;MyOtherPageLayout2" AssociatedContentType="CustomPage1" PageLayoutTemplate="AutoDetect" IncludeVerticalColumn="true" PageHeader="Custom">
      <SectionEmphasis VerticalColumnEmphasis="Soft">
        <Section Row="3" Emphasis="Neutral" />
      </SectionEmphasis>
      <Header Type="FullWidthImage" Alignment="Left" ShowPublishedDate="true">
        <Field Name="PublishingRollupImage;PublishingPageImage" HeaderProperty="ImageServerRelativeUrl" Functions="ToImageUrl({@name})" />
        <Field Name="ArticleByLine" HeaderProperty="TopicHeader" Functions=""/>
        <Field Name="PublishingContact" HeaderProperty="Authors" Functions="ToAuthors({PublishingContact})"/>
      </Header>
      <MetaData ShowPageProperties="true" PagePropertiesRow="1" PagePropertiesColumn="4" PagePropertiesOrder="1">
        <Field Name="PublishingContactName;PublishingContactEmail" TargetFieldName="MyPageContact" Functions="" />
        <Field Name="MyCategory" TargetFieldName="Category" Functions="" ShowInPageProperties="true" />
      </MetaData>
      <WebParts>
        <Field Name="PublishingPageImage" TargetWebPart="SharePointPnP.Modernization.WikiImagePart" Row="1" Column="1" Order="1">
          <Property Name="ImageUrl" Type="string" Functions="ToImageUrl({PublishingPageImage})"/>
          <Property Name="AlternativeText" Type="string" Functions="ToImageAltText({PublishingPageImage})" />
        </Field>
        <Field Name="PublishingPageContent" TargetWebPart="SharePointPnP.Modernization.WikiTextPart" Row="1" Column="2" Order="1">
          <Property Name="Text" Type="string" Functions="" />
        </Field>
      </WebParts>
      <WebPartZones>
        <WebPartZone Row="2" Column="1" Order="1" ZoneId="g_0C7F16935FAC4709915E2D77092A90DE" ZoneIndex="0">
          <!-- Optional element, only needed if you want to use custom position of the web parts coming from a web part zone -->
          <WebPartZoneLayout>
            <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="2"/>
            <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="1" Order="2"/>
            <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="1" Order="1"/>
          </WebPartZoneLayout>
        </WebPartZone>
      </WebPartZones>
      <FixedWebParts>
        <WebPart Row="1" Column="2" Order="1" Type="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
          <Property Name="TITLE" Type="string" Value="Example Embedded Web Content Editor"/>
          <Property Name="CONTENT" Type="string" Value="PnP Rocks!"/>
        </WebPart>
      </FixedWebParts>
    </PageLayout>

Observação

É recomendável que você use o esquema pagelayoutmapping.xsd ao editar esses arquivos. Os arquivos fornecidos à transformação da página serão validados em relação a esse esquema e a transformação falhará quando o arquivo de mapeamento de layout de página fornecido for inválido.

Elemento PageLayout

As propriedades a seguir são usadas no elemento PageLayout:

  • Nome: contém o nome do layout da página.
  • AlsoAppliesTo: quando esse mapeamento for usado para vários layouts de página, você poderá especificar os nomes desses layouts de página adicionais como uma lista delimitada por ponto e vírgula neste atributo. A propriedade Name será o nome do layout da primeira página, o AlsoAppliesTo contém apenas os adicionais.
  • AssociatedContentType: o nome do tipo de conteúdo de página de site moderno que você deseja usar. Deixe isso em branco se quiser usar o tipo de conteúdo de página do site padrão.
  • PageLayoutTemplate: o sistema de layout a ser usado ... AutoDetect os padrões devem funcionar bem em todos os casos, mas opcionalmente você também pode escolher um layout wiki específico.
  • IncludeVerticalColumn: elemento opcional para especificar que a página de destino criada deve ter uma coluna vertical. Ao usar uma coluna vertical, você direciona a coluna vertical como uma coluna extra, portanto, se antes de adicionar uma coluna vertical tinha 3 colunas, agora você terá 4 e, como tal, poderá definir o valor da coluna do conteúdo da página como 4 para colocá-lo na coluna vertical.
  • PageHeader: controla o tipo de cabeçalho de página que será usado. O padrão Custom é pois isso permite um bom cabeçalho, mas você pode mudá-lo para None sem cabeçalho ou Default para o cabeçalho de página moderno padrão.

Elemento SectionEmphasis

As propriedades a seguir são usadas no elemento opcional SectionEmphasis:

  • VerticalColumnEmphasis: use esta propriedade para definir a ênfase da coluna vertical como Nenhuma, Neutra, Suave ou Forte

Para cada seção, opcionalmente, você pode especificar uma ênfase de seção por meio do elemento Seção:

  • Linha: indica o número da linha desta seção, a primeira seção terá o número 1
  • Ênfase: define a ênfase da seção como Nenhuma, Neutra, Suave ou Forte

Elemento Header

As seguintes propriedades são usadas no elemento Header:

  • Tipo: o padrão é FullWidthImage permitir que o cabeçalho mostre a imagem do cabeçalho em largura total. As opções alternativas são ColorBlock, CutInShape e NoImage. Observe que esse atributo só é relevante quando o atributo PageHeader foi definido como Custom.
  • Alinhamento: controla como o conteúdo do cabeçalho da página é alinhado. O padrão é Left, a opção alternativa é Center.
  • ShowPublishedDate: define se a data de publicação da página é exibida. O padrão é true

Para cada campo que você deseja usar no cabeçalho moderno, você precisará adicionar um elemento Field especificando:

  • Nome: o nome do(s) campo(s) na página de publicação clássica. Por exemplo, adicionar PublishingRollupImage;PublishingPageImage como valor significará que o PublishingRollupImage será obtido se for preenchido, se não for preenchido, será PublishingPageImage tentado. Você pode adicionar quantas substituições precisar
  • HeaderProperty: o nome da propriedade de cabeçalho a ser definida
  • Funções: Se definido como vazio, o valor do campo da página de publicação clássica é considerado como está, no entanto, se você especificar uma função aqui, a saída dessa função será usada. Se você especificou vários campos (usando a opção de substituição de campo), precisará especificar o campo a ser usado na função como {@name}

Ao construir um cabeçalho de página moderno, há 4 propriedades de cabeçalho de página que você pode preencher com dados provenientes da página de publicação:

  • ImageServerRelativeUrl: Se o cabeçalho precisar mostrar uma imagem, esse campo precisará definir um caminho de imagem relativo do servidor para uma imagem que reside no mesmo conjunto de sites da página. Por padrão, o campo de página PublishingRollupImage de publicação clássico é usado, mas como ele contém uma tag Img, o conteúdo do campo é limpo por meio da ToImageUrl função.
  • TopicHeader: por padrão, o campo de página ArticleByLine de publicação clássico é usado como cabeçalho de tópico para o cabeçalho de página moderno
  • Autores: Definir os autores permite mostrar o contato principal desta página no cabeçalho da página. Por padrão, o campo de página PublishingContact de publicação clássico é usado, mas como é um campo de usuário, o conteúdo do campo é transformado por meio da ToAuthors função.
  • AlternativeText: não mapeado por padrão, mas você pode adicionar um mapeamento personalizado para preencher a propriedade de texto alternativo do cabeçalho moderno, se desejado

Se, por exemplo, você não quiser definir um cabeçalho de tópico, basta remover ou comentar o respectivo elemento Field.

Opções de imagem de cabeçalho de página

O mapeamento padrão usa a imagem definida no PublishingRollupImage campo como cabeçalho de página, mas você pode, opcionalmente, escolher outro campo de imagem de publicação ou especificar um valor embutido em código de uma imagem que reside no site de origem ou no site de destino. O exemplo abaixo mostra um cabeçalho com uma imagem estática:

<Header Type="FullWidthImage" Alignment="Left" ShowPublishedDate="true">
  <!-- Note that static values do require specifying them between '' -->
  <Field Name="PublishingRollupImage" HeaderProperty="ImageServerRelativeUrl" Functions="StaticString('/sites/classicportal/images/myimage.jpg')" />
  <Field Name="ArticleByLine" HeaderProperty="TopicHeader" Functions=""/>
  <Field Name="PublishingContact" HeaderProperty="Authors" Functions="ToAuthors({PublishingContact})"/>
</Header>

Elemento MetaData

O elemento metadata define quais dos campos clássicos da página de publicação precisam ser assumidos como metadados para a página moderna. Como às vezes você deseja que os metadados também sejam representados usando a Web Part de Propriedades da Página OOB, você indica isso por meio destes atributos opcionais:

  • ShowPageProperties: a Web Part de propriedades da página será adicionada à página moderna resultante
  • PagePropertiesRow: linha que conterá a Web Part de propriedades da página
  • PagePropertiesColumn: coluna que conterá a Web Part de propriedades da página
  • PagePropertiesOrder: a ordem da Web Part de propriedades da página na linha/coluna definida

Para cada campo que você deseja assumir, você precisará adicionar um elemento Field especificando:

  • Nome: o nome do(s) campo(s) na página de publicação clássica. Por exemplo, adicionar PublishingContactName;PublishingContactEmail como valor significará que o PublishingContactName será obtido se for preenchido, se não for preenchido, será PublishingContactEmail tentado. Você pode adicionar quantas substituições precisar
  • TargetFieldName: o nome do campo na página moderna de destino
  • Funções: Se definido como vazio, o valor do campo da página de publicação clássica é considerado como está, no entanto, se você especificar uma função aqui, a saída dessa função será usada. Se você especificou vários campos (usando a opção de substituição de campo), precisará especificar o campo a ser usado na função como {@name}
  • ShowInPageProperties: se definido como true e se mostrar que a Web Part de propriedades da página foi ativada, esse campo será mostrado na Web Part de propriedades da página

Observação

  • O suporte a funções não está disponível para campos de taxonomia

Elemento WebParts

Cada campo na página de publicação clássica que precisa se tornar um elemento visual na página de destino (como uma Web Part ou texto) deve ser definido na seção de Web Parts:

  • Nome: o nome do campo na página de publicação clássica.
  • TargetWebPart: o tipo da Web Part de destino que visualizará esse campo na página moderna. As Web Parts de destino com suporte são SharePointPnP.Modernization.WikiTextPart, SharePointPnP.Modernization.WikiImagePart e Microsoft.SharePoint.Publishing.WebControls.SummaryLinkWebPart, Microsoft.SharePoint.Publishing, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
  • Linha: a linha na qual você deseja colocar a Web Part de destino. Precisa ser 1 ou maior.
  • Coluna: a coluna na qual você deseja colocar a Web Part de destino. Precisa ser 1, 2 ou 3.
  • Ordem: a ordem da Web Part de destino na linha/coluna definida.

Dependendo da TargetWebPart escolhida, você precisará fornecer as propriedades da web part que contêm os dados necessários durante a transformação. Cada propriedade tem as seguintes propriedades:

  • Nome: Nome da propriedade. Esses nomes de propriedade precisam corresponder às propriedades usadas no modelo de transformação de página.
  • Tipo: Tipo da propriedade. Esses tipos de propriedade precisam corresponder às propriedades usadas no modelo de transformação de página.
  • Funções: Se definido como vazio, o valor da propriedade será o valor do campo na página de publicação clássica de origem. Você pode usar uma função para transformar primeiro o conteúdo do campo ou usar dados de outro campo da página de publicação clássica

Elemento WebPartZones

Se o layout da página contiver zonas de Web Part, elas deverão ser definidas aqui. Isso é necessário para posicionar corretamente as Web Parts transformadas na página moderna. As seguintes propriedades são usadas:

  • ZoneId: o nome da zona
  • ZoneIndex: o índice da zona (inteiro)
  • Linha: a linha na qual você deseja colocar as Web Parts hospedadas nessa zona. Precisa ser 1 ou maior.
  • Coluna: a coluna na qual você deseja colocar as Web Parts hospedadas nessa zona. Precisa ser 1, 2 ou 3.
  • Ordem: ordem na linha/coluna definida para as Web Parts hospedadas nesta zona

Às vezes, as páginas de publicação têm várias Web Parts em uma zona de Web Part e você deseja posicionar cada Web Part de maneira diferente na página de destino. Você pode fazer isso usando o elemento WebPartZoneLayout opcional:

<WebPartZoneLayout>
  <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="2"/>
  <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="1" Order="2"/>
  <WebPartOccurrence Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="3" Column="1" Order="1"/>
</WebPartZoneLayout>

A definição acima terá como resultado que o primeiro ContentEditorWebPart irá para a linha 3, coluna 2. A segunda ContentEditorWebPart será colocada na linha 3, coluna 1 com ordem 2 e a primeira web part XSLTListView terminará na linha 3, coluna 1 com ordem 1. Você pode definir quantos elementos WebPartOccurrence forem necessários, se não houver nenhuma web part correspondente na zona da web part, o elemento WebPartOccurrence será ignorado. Se houver uma web part na zona da web part que não esteja listada como um elemento WebPartOccurrence , essa web part obterá informações de linha, coluna e pedido do elemento WebPartZone.

Elemento FixedWebParts

Às vezes, os layouts de página contêm web parts "fixas", essas são web parts codificadas dentro do layout da página e, portanto, estão presentes em todas as páginas que usam o layout da página. Como não há APIs para detectar essas Web Parts "fixas", elas precisam ser definidas como parte do modelo de mapeamento de layout da página.

As seguintes propriedades podem ser definidas em uma web part "fixa":

  • Tipo: tipo da Web Part fixa. Veja aqui uma lista dos tipos possíveis.
  • Linha: a linha na qual você deseja colocar a web part "fixa". Precisa ser 1 ou maior.
  • Coluna: a coluna na qual você deseja colocar a web part "fixa". Precisa ser 1, 2 ou 3.
  • Ordem: a ordem, relevante se houver várias Web Parts que você coloca na mesma linha e coluna.

Para cada Web Part "fixa", você precisa definir as propriedades relevantes. Normalmente, você assumiria essas propriedades conforme elas são definidas no layout de página clássico. Para cada propriedade, os seguintes atributos podem ser definidos:

  • Propriedade: Nome da propriedade. Esses nomes de propriedade precisam corresponder às propriedades usadas no modelo de transformação de página.
  • Tipo: Tipo da propriedade. Esses tipos de propriedade precisam corresponder às propriedades usadas no modelo de transformação de página.
  • Valor: o valor que esta propriedade tem. Não se esqueça de codificar o valor em XML.

Definição de complementos no modelo de layout de página

Os complementos permitem que você insira sua lógica personalizada no modelo de mapeamento de layout de página seguindo estas 2 etapas:

  • Criar um assembly personalizado que hospeda suas funções personalizadas
  • Declare este assembly personalizado nos elementos AddOns

Criar seu assembly de funções/seletores personalizado

Para criar suas próprias funções, você precisará fazer referência ao assembly SharePoint.Modernization.Framework no projeto e criar uma classe que herde a classe SharePointPnP.Modernization.Framework.Functions.FunctionsBase:

using Microsoft.SharePoint.Client;
using SharePointPnP.Modernization.Framework.Functions;
using System;

namespace Contoso.Modernization
{
    public class MyCustomFunctions: FunctionsBase
    {
        public MyCustomFunctions(ClientContext clientContext) : base(clientContext)
        {
        }

        public string MyListAddServerRelativeUrl(Guid listId)
        {
            if (listId == Guid.Empty)
            {
                return "";
            }
            else
            {
                var list = this.clientContext.Web.GetListById(listId);
                list.EnsureProperties(p => p.RootFolder.ServerRelativeUrl);
                return list.RootFolder.ServerRelativeUrl;
            }
        }

    }
}

Declarar seu assembly personalizado

Antes de as funções personalizadas poderem ser usadas, elas precisam ser declaradas no modelo, incluindo uma referência por biblioteca/classe no elemento AddOns:

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="Contoso.Modernization.dll" />

ou (observe o caminho qualificado completo)

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="c:\transform\Contoso.Modernization.dll" />

Observe que cada declaração tem um nome "Custom" (personalizado) no exemplo acima.

Usar seus seletores/funções personalizados

Agora que o assembly foi definido, você poderá usar as funções e seletores fazendo referência a eles pelo nome, como você pode ver o prefixo "Custom" no exemplo abaixo:

<Property Name="ListId" Type="guid" Functions="{ListServerRelativeUrl} = Custom.MyListAddServerRelativeUrl({ListId})"/>

Perguntas frequentes sobre mapeamento de layout de página

Quero manter as informações de criação da página de origem

Ao usar a abordagem PnP do PowerShell , use o -KeepPageCreationModificationInformationConvertTo-PnPPage cmdlet no cmdlet. Quando você estiver usando a abordagem .Net , defina o KeepPageCreationModificationInformation parâmetro como true. Usar esta opção dará à página de destino os valores de campo Criado, Modificado, Autor e Editor da página de origem.

Observação

Quando você, como parte da transformação da página, promover a página como notícia ou publicar a página, o campo Editor será definido como a conta que executa a transformação da página

Quero promover as páginas criadas como notícias

A promoção de páginas criadas a partir de um layout de página como páginas de notícias pode ser feita usando o -PostAsNews parâmetro no -KeepPageCreationModificationInformation cmdlet (quando você estiver usando a abordagem PnP do PowerShell) ou, alternativamente, definindo o PostAsNews parâmetro como true (ao usar a abordagem .Net).

Quando você usa a PostAsNews opção em conjunto com a KeepPageCreationModificationInformation opção, o FirstPublishedDateField campo será definido como a data de modificação da página de origem. O FirstPublishedDateField campo é o valor de data mostrado durante o acúmulo de notícias.

Quero inserir texto embutido em código na página criada

Às vezes, um layout de página contém trechos de texto que, como não estão contentes na página real, não estão sendo transformados. Se for esse o caso, você pode definir um campo "falso" para mapear, conforme mostrado abaixo:

<WebParts>
  ...
  <Field Name="ID" TargetWebPart="SharePointPnP.Modernization.WikiTextPart" Row="1" Column="3">
    <Property Name="Text" Type="string" Functions="StaticString('&lt;H1&gt;This is some extra text&lt;/H1&gt;')" />
  </Field>
  ...
</WebParts>

Observação

O HTML fornecido na função StaticString deve ser codificado em XML e deve ser formatado como o HTML da página de origem, pois esse HTML ainda será convertido em HTML compatível com o editor de texto moderno

Quero prefixar ou sufixar o conteúdo do campo

A abordagem usada no capítulo anterior permite adicionar texto extra em uma página, mas tem como desvantagem que o texto extra será adicionado em sua própria parte de texto. Se você deseja que o texto extra seja integrado ao texto real que está sendo transformado, a abordagem abaixo permite que você faça isso. Você pode prefixar e/ou sufixar o conteúdo do campo existente e, opcionalmente, só pode ter o prefixo/sufixo feito quando o campo tiver conteúdo. O parâmetro bool nas Prefixfunções and SuffixPrefixAndSuffix define se o prefixo/sufixo precisa acontecer quando o conteúdo do campo está vazio: 'true' significa aplicar a ação mesmo quando o campo está vazio.

Consulte Funções e seletores de transformação de página para obter mais detalhes sobre as funções abaixo.

<WebParts>
...
  <Field Name="PublishingPageContent" TargetWebPart="SharePointPnP.Modernization.WikiTextPart" Row="1" Column="2">
    <Property Name="Text" Type="string" Functions="PrefixAndSuffix('&lt;H1&gt;Prefix some extra text&lt;/H1&gt;','&lt;H1&gt;Suffix some extra text&lt;/H1&gt;',{PublishingPageContent},'false')" />
  </Field>
  ...
  <Field Name="PublishingPageContent" TargetWebPart="SharePointPnP.Modernization.WikiTextPart" Row="1" Column="2">
    <Property Name="Text" Type="string" Functions="Prefix('&lt;H1&gt;Prefix some extra text&lt;/H1&gt;',{PublishingPageContent},'true')" />
  </Field>
  ...
  <Field Name="PublishingPageContent" TargetWebPart="SharePointPnP.Modernization.WikiTextPart" Row="1" Column="2">
    <Property Name="Text" Type="string" Functions="Suffix('&lt;H1&gt;Suffix some extra text&lt;/H1&gt;',{PublishingPageContent},'false')" />
  </Field>
...
</WebParts>

Quero preencher um campo de metadados gerenciados com um ou mais termos

Quando você tem um campo de metadados gerenciados nos metadados da página de origem, talvez queira ter um campo de metadados gerenciados semelhante para a página de destino. Considerando que a transformação de página atualmente tem um recurso de mapeamento de metadados gerenciados, isso representa um problema. Uma possível solução alternativa é preencher o campo de metadados gerenciados de destino com um termo escolhido ou um conjunto de termos no caso de um campo de metadados gerenciados de vários valores. Isso pode ser feito usando a função mostrada DefaultTaxonomyFieldValue no exemplo abaixo:

<MetaData ShowPageProperties="true" PagePropertiesRow="1" PagePropertiesColumn="4" PagePropertiesOrder="1">
...
  <Field Name="TaxField2" TargetFieldName="Metadata2" Functions="DefaultTaxonomyFieldValue({TaxField2},'a65537e8-aa27-4b3a-bad6-f0f61f84b9f7|69524923-a5a0-44d1-b5ec-7f7c6d0ec160','true')" ShowInPageProperties="true"/>
...
</MetaData>

Consulte Funções e seletores de transformação de página para obter mais detalhes sobre a DefaultTaxonomyFieldValue função.

Quero adicionar uma Web Part extra à página criada

Quando você transforma sua página de publicação clássica em uma página moderna, às vezes você deseja adicionar uma Web Part moderna adicional na página criada, sem que haja uma versão clássica dessa Web Part na página de publicação clássica. Isso pode ser feito ajustando o webpartmapping.xml e os arquivos de mapeamento de layout de página, conforme mostrado abaixo.

Primeiro, defina sua web part personalizada no arquivo webpartmapping.xmladicionando a ela o WebParts elemento no arquivo, como mostrado nesta web part de Olá, Mundo SPFX padrão:

<WebParts>
  ...
  <!-- Custom Hello world web part-->
  <WebPart Type="SharePointPnP.Demo.HelloWorld" CrossSiteTransformationSupported="true">
    <Properties>
      <Property Name="HelloWorld" Type="string" />
    </Properties>
   <Mappings>
    <Mapping Default="true" Name="default">
      <ClientSideWebPart Type="Custom" ControlId="157b22d0-8006-4ec7-bf4b-ed62383fea76" Order="10" JsonControlData="&#123;&quot;serverProcessedContent&quot;:&#123;&quot;htmlStrings&quot;:&#123;&#125;,&quot;searchablePlainTexts&quot;:&#123;&#125;,&quot;imageSources&quot;:&#123;&#125;,&quot;links&quot;:&#123;&#125;&#125;,&quot;dataVersion&quot;:&quot;1.0&quot;,&quot;properties&quot;:&#123;&quot;description&quot;:&quot;{HelloWorld}&quot;,&quot;test&quot;:&quot;Multi-line text field&quot;,&quot;test1&quot;:true,&quot;test2&quot;:&quot;2&quot;,&quot;test3&quot;:true&#125;&#125;"/>
    </Mapping>
  </Mappings>
</WebPart>
  ...
</WebParts>

Se você não souber como definir corretamente sua web part personalizada no elemento ClientSideWebPart acima, siga estas etapas:

  • Navegue até o Workbench da Estrutura do SharePoint em seu site (por exemplohttps://contoso.sharepoint.com/sites/myportalsite/_layouts/workbench.aspx)
  • Adicione sua Web Part personalizada ao workbench e configure-a quando necessário
  • Clique no botão "Dados da Web part" na barra de ferramentas e depois no botão "Páginas modernas"
  • Copie a estrutura json WebPartData e use-a para concluir as próximas etapas:
    • O valor guid ControlId é o valor da propriedade id json
    • Exclua as seguintes propriedades json do snippet copiado: id, instanceIf, title e description. Neste ponto, você tem o seguinte: {"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"description":"HelloWorld from Bert","test":"Multi-line text field","test1":true,"test2":"2","test3":true}}
    • Codificar XML esta cadeia de caracteres, isso lhe dará isso: &#123;&quot;serverProcessedContent&quot;:&#123;&quot;htmlStrings&quot;:&#123;&#125;,&quot;searchablePlainTexts&quot;:&#123;&#125;,&quot;imageSources&quot;:&#123;&#125;,&quot;links&quot;:&#123;&#125;&#125;,&quot;dataVersion&quot;:&quot;1.0&quot;,&quot;properties&quot;:&#123;&quot;description&quot;:&quot;HelloWorld from Bert&quot;,&quot;test&quot;:&quot;Multi-line text field&quot;,&quot;test1&quot;:true,&quot;test2&quot;:&quot;2&quot;,&quot;test3&quot;:true&#125;&#125;
    • Se necessário, insira os parâmetros da Web Part nesta cadeia de caracteres (por exemplo, {HelloWorld} no exemplo acima): &#123;&quot;serverProcessedContent&quot;:&#123;&quot;htmlStrings&quot;:&#123;&#125;,&quot;searchablePlainTexts&quot;:&#123;&#125;,&quot;imageSources&quot;:&#123;&#125;,&quot;links&quot;:&#123;&#125;&#125;,&quot;dataVersion&quot;:&quot;1.0&quot;,&quot;properties&quot;:&#123;&quot;description&quot;:&quot;{HelloWorld}&quot;,&quot;test&quot;:&quot;Multi-line text field&quot;,&quot;test1&quot;:true,&quot;test2&quot;:&quot;2&quot;,&quot;test3&quot;:true&#125;&#125;
    • Cole a cadeia de caracteres resultante na propriedade JsonControlData

Depois que isso estiver em vigor, você precisa atualizar o mapeamento do layout da página adicionando um campo na seção WebParts que será transformado nesta Web Part personalizada:

<WebParts>
  ...
  <!-- Add an extra web part on the page -->
  <Field Name="ID"  TargetWebPart="SharePointPnP.Demo.HelloWorld" Row="4" Column="1" Order="1">
    <Property Name="HelloWorld" Type="string" Functions="StaticString('PnP Rocks!')"/>
  </Field>
  ...
</WebParts>

Certifique-se de especificar o arquivo dewebpartmapping.xml personalizado como parte de sua transformação (-WebPartMappingFile parâmetro de cmdlet do PowerShell, PublishingPageTransformator construtor ao usar o .Net).

Estou usando muitas Add-In parts e quero transformá-las em web parts SPFX personalizadas

O comportamento padrão da transformação de página é simplesmente assumir a parte do suplemento na página moderna, pois os suplementos funcionam em páginas modernas. Se, no entanto, você quiser transformar seletivamente algumas partes do suplemento em Web Parts personalizadas baseadas em SPFX, descartar algumas das partes do suplemento e manter as partes restantes do complemento, o mapeamento padrão não será suficiente. No exemplo abaixo, você vê que a StaticString função é usada para alimentar o título do suplemento como valor do seletor de mapeamento. Portanto, com base no título da Web Part, um mapeamento será selecionado. O primeiro suplemento será assumido como suplemento na página moderna, o segundo será transformado em uma alternativa personalizada baseada em SPFX e o último será simplesmente descartado.

Ao mapear para uma Web Part baseada em SPFX personalizada, você pode usar qualquer uma das propriedades da parte do suplemento para configurar a alternativa baseada em SPFX (por exemplo, {HelloWorld} no exemplo abaixo), mesmo que essas propriedades não estejam listadas no nó Propriedades no arquivo de mapeamento. Consulte também o capítulo anterior se quiser saber mais sobre como criar um arquivo de mapeamento personalizado.

<WebPart Type="Microsoft.SharePoint.WebPartPages.ClientWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" CrossSiteTransformationSupported="true">
  <!-- Note: the add-in can depend on assets that live in the source site, which is not something we can detect -->
  <Properties>
    <Property Name="FeatureId" Type="guid"/>
    <Property Name="ProductWebId" Type="guid"/>
    <Property Name="ProductId" Type="guid"/>
  </Properties>
  <Mappings Selector="StaticString({Title})">
    <Mapping Name="My Custom Report" Default="true">
      <!-- We keep this web part -->
      <ClientSideWebPart Type="ClientWebPart" Order="10" JsonControlData="{}"/>
    </Mapping>
    <Mapping Name="News Ticker" Default="false">
      <!--This web part will be transformed to a custom SPFX based web part -->
      <ClientSideWebPart Type="Custom" ControlId="157b22d0-8006-4ec7-bf4b-ed62383fea76" Order="10" JsonControlData="&#123;&quot;serverProcessedContent&quot;:&#123;&quot;htmlStrings&quot;:&#123;&#125;,&quot;searchablePlainTexts&quot;:&#123;&#125;,&quot;imageSources&quot;:&#123;&#125;,&quot;links&quot;:&#123;&#125;&#125;,&quot;dataVersion&quot;:&quot;1.0&quot;,&quot;properties&quot;:&#123;&quot;description&quot;:&quot;{HelloWorld}&quot;,&quot;test&quot;:&quot;Multi-line text field&quot;,&quot;test1&quot;:true,&quot;test2&quot;:&quot;2&quot;,&quot;test3&quot;:true&#125;&#125;"/>
    </Mapping>
    <Mapping Name="Some other add-in" Default="false">
      <!-- This add-in will not be taken over -->
    </Mapping>
  </Mappings>
</WebPart>

Você pode até tornar o mapeamento mais preciso, levando em consideração as propriedades da peça de complemento, combinando as propriedades da peça de suplemento para gerar uma string de seletor.

<WebPart Type="Microsoft.SharePoint.WebPartPages.ClientWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" CrossSiteTransformationSupported="true">
  <!-- Note: the add-in can depend on assets that live in the source site, which is not something we can detect -->
  <Properties>
    <Property Name="FeatureId" Type="guid"/>
    <Property Name="ProductWebId" Type="guid"/>
    <Property Name="ProductId" Type="guid"/>
  </Properties>
  <Mappings Selector="ConcatenateWithPipeDelimiter({Title},{effect})">
    <Mapping Name="News Ticker|Slide" Default="true">
      <ClientSideText Text="***TEST.{Title} web part - Slide mapping chosen! Slider theme = {theme}***" Order="10" />
    </Mapping>
    <Mapping Name="News Ticker|Scroll" Default="false">
      <ClientSideText Text="***TEST.{Title} web part - Scroll mapping chosen! Slider theme = {theme}***" Order="10" />
    </Mapping>
  </Mappings>
</WebPart>

Posso controlar a imagem de visualização da página?

Quando uma página tiver uma imagem de cabeçalho de página, essa imagem também será usada como uma imagem de visualização de página. Se, no entanto, você quiser controlar a imagem de visualização da página, poderá preencher o BannerImageUrl campo usando a ToPreviewImageUrl função ou especificando um valor embutido em código, conforme mostrado nos exemplos abaixo.

<!-- When you do have a publishing image field that will need to be set as preview image -->
<Field Name="PreviewImage" TargetFieldName="BannerImageUrl" Functions="ToPreviewImageUrl({PreviewImage})" />

<!-- When you do have a hard coded preview image already available on the target site. Note that the source field name (PublishingContactEmail in below sample) must exist, although it's not used here  -->
<Field Name="PublishingContactEmail" TargetFieldName="BannerImageUrl" Functions="StaticString('https://contoso.sharepoint.com/_layouts/15/getpreview.ashx?guidSite=88eebac1710b464cb6816639340fac55&amp;guidWeb=277fe40db9d24da5bbc6827714184958&amp;guidFile=91bf17fd54e849149a3ad6b4f006304e&amp;ext=jpg')" />

<!-- When you want to refer a static image living in the source site  -->
<Field Name="PreviewImage" TargetFieldName="BannerImageUrl" Functions="ToPreviewImageUrl('/sites/classicportal/images/myimage.jpg')" />

Quando a transformação resulta em uma Web Part de Links Rápidos moderna (por exemplo, para a transformação da SummaryLinkWebPart), a estrutura de transformação de página usará uma configuração básica padrão para a Web Part de Links Rápidos. Se, no entanto, você quiser uma configuração diferente, poderá fazer isso especificando a propriedade QuickLinksJsonProperties. Encapsule as propriedades JSON codificadas em uma função StaticString, conforme mostrado neste exemplo:

<WebParts>
  ...
  <Field Name="SummaryLinks" TargetWebPart="Microsoft.SharePoint.Publishing.WebControls.SummaryLinkWebPart, Microsoft.SharePoint.Publishing, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Row="1" Column="2">
    <!-- No function specified, means the content of the PublishingPageContent field will be assigned to the value of the first listed web part property -->
    <Property Name="SummaryLinkStore" Type="string" />
    <Property Name="Title" Type="string" Functions="EmptyString()"/>
    <Property Name="QuickLinksJsonProperties" Type="string" Functions="StaticString('{&quot;isMigrated&quot;: false, &quot;layoutId&quot;: &quot;Button&quot;, &quot;shouldShowThumbnail&quot;: true, &quot;buttonLayoutOptions&quot;: { &quot;showDescription&quot;: false, &quot;buttonTreatment&quot;: 1, &quot;iconPositionType&quot;: 2, &quot;textAlignmentVertical&quot;: 1, &quot;textAlignmentHorizontal&quot;: 2, &quot;linesOfText&quot;: 2}, &quot;listLayoutOptions&quot;: { &quot;showDescription&quot;: false, &quot;showIcon&quot;: true}, &quot;waffleLayoutOptions&quot;: { &quot;iconSize&quot;: 1, &quot;onlyShowThumbnail&quot;: false}, &quot;hideWebPartWhenEmpty&quot;: true}')" />
  </Field>
  ...
</WebParts>

O JSON no exemplo mostra todas as opções de configuração possíveis que você pode definir, mas você também pode definir as que precisa. Enquanto o JSON for válido e a estrutura for mantida, sua configuração personalizada de QuickLinks será escolhida.