Fermer

octobre 12, 2020

Episerver et texte alternatif pour les images dans l'éditeur de texte enrichi TinyMCE


La semaine dernière, j'ai reçu un rapport de bogue désagréable concernant l'accessibilité et Episerver. Dans les zones Rich Text d'Episerver, le nom du fichier est injecté par défaut pour le texte alternatif. Cela nuit à votre score d'accessibilité et a un impact négatif sur les utilisateurs malvoyants. Par coïncidence, d'autres membres de la communauté ont écrit et se sont demandé comment résoudre ce problème:

Je ne peux pas m'attribuer tout le mérite de ma solution car la solution de Tomas Hensrud Gulla m'a fourni la sauce secrète: l'analyse des fragments XhtmlString. Son article de blog a inspiré ma solution. Gardez également à l'esprit que ce comportement est reconnu par Episerver comme un bogue, et peut être corrigé dans les versions futures: https://world.episerver.com/support/Bug-list/bug/CMS-16633[19659003OftinjectiondetextealternatifdansEpiserver«parlelivre»

Si vous êtes nouveau sur Episerver, ou si vous travaillez dans la plate-forme depuis un certain temps, vous rencontrerez inévitablement le besoin d'afficher un texte alternatif sur les ressources Image. Le texte alternatif est un mécanisme permettant de fournir des métadonnées supplémentaires sur les images aux utilisateurs malvoyants et de fournir un avantage SEO minimal pour les moteurs de recherche. Si vous recherchez ou jetez un œil à Alloy (l'un des sites de démonstration d'Episerver), vous verrez une approche assez standard pour fournir un texte alternatif dans les images:

  1. Étendez ImageFile.cs avec une nouvelle classe qui a une propriété de chaîne for AltText
  2. Créez un modèle d'affichage pour Image.cshtml qui utilise votre classe personnalisée comme modèle et injecte un texte alternatif en conséquence.

Si vous suivez dans Alloy, vous pouvez voir que cela est fait ici:

The Problème

 SAS IDC Episerver Commerce Guide

Le problème survient lorsque vos auteurs de contenu souhaitent placer des images dans des champs Rich Text. Si vous utilisez XhtmlString (texte enrichi) sur votre solution Episerver, l'une des options par défaut consiste à autoriser le glisser-déposer des éléments multimédias dans l'éditeur de texte enrichi ou à permettre aux utilisateurs de sélectionner une image via des commandes TinyMCE spécifiques. Lorsque cela se produit, cependant, Episerver utilise le nom de l'image (par défaut le nom du fichier au moment du téléchargement) comme texte alternatif. Il en résulte un balisage qui n’aide pas du tout les utilisateurs accessibles:  https://i0.wp.com/blogs.perficient.com/somefile.jpg?w=660

La solution

La solution est assez simple. Au moment du rendu, nous pouvons intercepter XhtmlString (le type de propriété de support pour le texte enrichi) et modifier ce qui est rendu. Cela semble assez facile, non? Voici comment procéder…

Commencez par créer un modèle d'affichage pour XhtmlString.cshtml et assurez-vous qu'il est correctement câblé pour votre solution:

 @using EPiServer.Core
@model XhtmlString

@ Html.Raw (Model.FixAlternateText (ViewContext)) 

Deuxièmement, créons la méthode d'extension pour FixAlternateText () . Dans cette méthode d'extension, nous aurons besoin du ViewContext pour pouvoir demander à Episerver de rendre les résultats pour modification. En effet, Episerver fait de la magie pour appliquer la personnalisation, les blocs de rendu, etc. dans le contenu des champs XhtmlString, et a besoin du ViewContext pour le faire. Une fois que nous avons le résultat HTML d'Episerver, nous pouvons utiliser HtmlAgilityPack pour analyser le HTML résultant et l'ajuster si nécessaire.

Ma méthode d'extension ressemble à ceci:

 chaîne statique publique FixAlternateText (ce html XhtmlString, contexte ViewContext)
{
    // html est nul lorsque le TinyMce n'est pas initialisé (création d'un nouveau bloc, etc.), il suffit donc de retourner
    if (html == null) return string.Empty;

    // générer un dictionnaire de  sous forme de chaînes. Comportement epi par défaut
    // consiste à injecter ContentName comme texte alternatif de l'image, et ContentName
    // prend par défaut le nom de fichier lors du téléchargement via l'interface utilisateur. Cela conduit à un texte alternatif
    // étant défini sur le nom du fichier, ce qui revient essentiellement à n'avoir aucun texte alternatif.
    var altTextDictionary = GenerateAltTextDictionary (html.Fragments);

    // Chargez HtmlHelper d'Epi et demandez-lui de rendre les résultats
    var hh = new HtmlHelper (contexte, nouveau ViewPage ());
    string epiRenderingResult;
    en utilisant (var writer = new StringWriter ())
    {
        hh.ViewContext.Writer = écrivain;
        hh.RenderXhtmlString (html);
        écrivain.Flush ();
        epiRenderingResult = writer.ToString ();
    }

    // nous ne nous soucions pas du mode d'édition, renvoyez simplement le résultat HTML
    if (PageEditing.PageIsInEditMode)
        return epiRenderingResult;

    // une fois les résultats rendus, chargez HtmlAgilityPack et faites-le analyser les résultats
    var doc = nouveau HtmlDocument ();
    doc.LoadHtml (epiRenderingResult);

    // trouve toutes les balises d'image, s'il n'y en a pas, retourne simplement - sinon nous devons les ajuster
    var imgs = doc.DocumentNode.SelectNodes ("// img");
    si (imgs == null)
        return epiRenderingResult;

    // pour chaque image, remplacez alt = "name" par alt = "alt text" pour l'accessibilité
    foreach (var img dans imgs)
    {
        var src = img.Attributes ["src"] .Value;

        // si nous connaissons ce texte alternatif par clé, remplacez-le par la valeur de la clé
        // rappelez-vous, le dictionnaire contient 
        if (altTextDictionary.ContainsKey (src))
        {
            img.SetAttributeValue ("alt", altTextDictionary [src]);
        }
    }

    var externalHtml = doc.DocumentNode.OuterHtml;
    return externalHtml; // retourne le nouveau HTML résultant
}

Dictionnaire statique privé  GenerateAltTextDictionary (StringFragmentCollection htmlFragments)
{
    var _contentLoader = ServiceLocator.Current.GetInstance  (); // beurk, mais que peux-tu faire? :)

    Dictionnaire  retVal = new Dictionary  ();

    foreach (var urlFragment dans htmlFragments.Where (x => x est UrlFragment))
    {
        foreach (var guid dans urlFragment.ReferencedPermanentLinkIds)
        {
            // en supposant que notre modèle ImageData personnalisé s'appelle "ImageFile" avec une propriété "AltText"
            if (_contentLoader.TryGet (guid, out ImageFile image))
            {
                var key = image.ContentLink.GetPublicUrl ();
                if (! retVal.ContainsKey (clé))
                {
                    retVal.Add (clé, image.AltText); // vous voudrez peut-être nettoyer AltText pour un balisage HTML correct
                }
            }
        }
    }

    return retVal;
} 

Après avoir déployé cette modification, à chaque fois qu'une chaîne XhtmlString est rendue, nous l'interceptons maintenant et ajustons son texte alternatif en conséquence.

J'espère que cela vous aidera dans votre voyage Episerver!

À propos de l'auteur <! -: dmccurry, Architecte de solutions ->

Je suis un développeur Sitecore certifié, un singe de code et un nerd général. J'ai sauté dans l'espace .NET il y a 10 ans pour travailler sur des applications de classe entreprise et je n'ai jamais regardé en arrière. J'adore créer des choses, des Legos aux logiciels qui résolvent de vrais problèmes. Ai-je mentionné que j'aime les jeux vidéo?

Plus de cet auteur






Source link