Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events

content fragment strikethrough node type on graphql query

Avatar

Level 4

Hi team,

        We are in AEMasCS, we implemented strikethrough plugin in our contentfragment  RTE model, while explore the graphql json data, we are getting the "nodeType" as "span" instead of nodeType as "strikethrough", kindly let us know is there any option to change the "nodeType" as "strikethrough", pfb our graphql json data.

rajat168_0-1718268290953.pngrajat168_1-1718268323256.png

 

9 Replies

Avatar

Community Advisor

Hi @rajat168 
Could you please check, how the data is stored in the JCR? with span Tag or with strikethrough Tag?



Arun Patidar

Avatar

Level 4

Hi @arunpatidar , thanks for your response, its stored as <span> tag. but we need the tag as <strikethrough>

rajat168_0-1718270020911.png

 

Avatar

Community Advisor

Hi @rajat168 
Then you need to check your RTE custom plugin implementation, you might be saving content using span instaedof strikethrough Tag.



Arun Patidar

Avatar

Level 4

ya @arunpatidar , in css we are providing span tag as below, is there any way to change span to strikethrough?

rajat168_0-1718274588235.png

 

Avatar

Community Advisor

Hi @rajat168 
The CSS is to show red strikethrough line but you need to check the JS part with add the span with strikethrough class.

can you share the js code which is used to wrap text into span with strikethrough CSS class.



Arun Patidar

Avatar

Level 4

Hi @arunpatidar , pfb jscode 

/*
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2017 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

(function($, ns, window) {
    'use strict';

    var defaultCFMRTEConfig = {
        "useFixedInlineToolbar": "true",
        "rtePlugins": {
          "links": {
            "features": "*"
          },
          "misctools": {
            "features": "*"
          },
          "edit": {
            "features": "*"
          },
          "findreplace": {
            "features": "*"
          },
          "format": {
            "features": "*"
          },
          "image": {
            "features": "*"
          },
          "keys": {
            "features": "*"
          },
          "justify": {
            "features": "*"
          },
          "lists": {
            "features": "*"
          },
          "paraformat": {
            "features": "*"
          },
          "spellcheck": {
            "features": "*"
          },
          "styles": {
            "features": "*",
            "styles": {
              "strikethrough": {
            "text": "StrikeThrough",
            "cssName": "strikethrough"
				}             
            }
          },
          "subsuperscript": {
            "features": "*"
          },
          "table": {
            "features": "*"
          },
          "undo": {
            "features": "*"
          },
          "generichtml": {
            "features": "*",
            "tools": {
              "comment": {
                "editor": "rawpayload",
                "converter": "comment",
                "editorConfig": {
                  "processor": "comment",
                  "title": "Edit Comment"
                }
              }
            }
          },
          "assets": {
            "features": "*",
              "tooltips": {
                  "insertasset": {
                      "title": Granite.I18n.get("Insert asset"),
                      "text": Granite.I18n.get("Insert asset")
                  }
              }
          },
          "contentfragment": {
            "features": "*",
              "tooltips": {
                  "insertcontentfragment": {
                      "title": Granite.I18n.get("Insert Content Fragment"),
                      "text": Granite.I18n.get("Insert Content Fragment")
                  }
              }
          },
          "cfmAnnotate": {
            "features": "*",
            "tooltips": {
              "annotate": {
                 "title": Granite.I18n.get("Annotate"),
                 "text": Granite.I18n.get("Annotate")
              }
            }
          }
        },
        "uiSettings": {
          "cui": {
            "additionalClasses": {
              "fullscreenstart": {
                "classes": "",
                "command": "fullscreen#start"
              }
            },
            "inline": {
              "toolbar": [
                "#format",
                "#justify",
                "#lists",
                "links#modifylink",
                "links#unlink",
                "assets#insertasset",
                "#styles",
                "contentfragment#insertcontentfragment"
              ],
              "popovers": {
                "justify": {
                  "ref": "justify",
                  "items": [
                    "justify#justifyleft",
                    "justify#justifycenter",
                    "justify#justifyright"
                  ]
                },
                "lists": {
                  "ref": "lists",
                  "items": [
                    "lists#unordered",
                    "lists#ordered",
                    "lists#outdent",
                    "lists#indent"
                  ]
                },
                "paraformat": {
                  "ref": "paraformat",
                  "items": "paraformat:getFormats:paraformat-pulldown"
                },
                "format": {
                  "ref": "format",
                  "items": [
                    "format#bold",
                    "format#italic",
                    "format#underline"
                  ]
                },
                "styles": {
                    "ref": "styles",
                    "items": "styles:getStyles:styles-pulldown"
                }
              }
            },
            "multieditorFullscreen": {
              "toolbar": [
                "#format",
                "#justify",
                "#lists",
                "links#modifylink",
                "links#unlink",
                "edit#paste-plaintext",
                "edit#paste-wordhtml",
                "table#createoredit",
                "#paraformat",
                "#styles",
                /* "image#imageProps", */
                "assets#insertasset",
                "contentfragment#insertcontentfragment",
                "findreplace#find",
                "findreplace#replace",
                "spellcheck#checktext",
                "cfmAnnotate#annotate"
              ],
              "popovers": {
                "paraformat": {
                  "ref": "paraformat",
                  "items": "paraformat:getFormats:paraformat-pulldown"
                },
                "justify": {
                  "ref": "justify",
                  "items": [
                    "justify#justifyleft",
                    "justify#justifycenter",
                    "justify#justifyright"
                  ]
                },
                "lists": {
                  "ref": "lists",
                  "items": [
                    "lists#unordered",
                    "lists#ordered",
                    "lists#outdent",
                    "lists#indent"
                  ]
                },
                "format": {
                  "ref": "format",
                  "items": [
                    "format#bold",
                    "format#italic",
                    "format#underline"
                  ]
                },
                "styles": {
                    "ref": "styles",
                    "items": "styles:getStyles:styles-pulldown"
                }
              }
            },
            "tableEditOptions": {
              "toolbar": [
                "table#insertcolumn-before",
                "table#insertcolumn-after",
                "table#removecolumn",
                "-",
                "table#insertrow-before",
                "table#insertrow-after",
                "table#removerow",
                "-",
                "table#mergecells-right",
                "table#mergecells-down",
                "table#mergecells",
                "table#splitcell-horizontal",
                "table#splitcell-vertical",
                "-",
                "table#selectrow",
                "table#selectcolumn",
                "-",
                "table#ensureparagraph",
                "-",
                "table#modifytableandcell",
                "table#removetable",
                "-",
                "undo#undo",
                "undo#redo",
                "-",
                "table#exitTableEditing",
                "-"
              ]
            }
          }
        },
        "htmlRules": {
            "genericHtml": {
                "converters": [
                    {
                        "type": "video",
                        "name": "video",
                        "detectors": [
                            {
                                "type": "element",
                                "tagName": "video"
                            }
                        ],
                        "thumbnailMaxWidth": 240,
                        "keepEmptyContainers": true
                    }, {
                        "type": "imagethumb",
                        "name": "imagethumb",
                        "detectors": [
                            {
                                "type": "element",
                                "tagName": "img"
                            }
                        ],
                        "thumbnailMaxWidth": 240,
                        "keepEmptyContainers": true
                    }
                ]
            }
        }
    };

    var channel = $(window.document);

    /**
     * options = {
     *     $formViewContainer: 'element in whose subtree form view RTE's editable is present'
     *     selectorForEditable: 'selector for editable',
     *     $textField: 'text field to store value to be submitted',
     *     editorType: 'text or table',
     *     externalStyleSheets: 'array of links to stylesheets for style plugin',
     *     customStart: 'true if editing should be triggered by rte-start event on editable, false otherwise'
     *     $rteToolbarContainer: 'dom under which toolbar of this editor should reside'
     * }
     */
    ns.StyledTextEditor = function(options) {
        ns.CFMEditor.call(this, options);
        this.rte = undefined;
        this.options = $.extend({}, options);
        this.$formViewContainer = this.options.$formViewContainer;
        this.$textField = this.options.$textField;
        this.editorType = this.options.editorType;
        this.externalStyleSheets = this.options.externalStyleSheets;
        this.htmlExtractor = new ns.HTMLExtractor();
        this._styleElements = [];
        if (this.externalStyleSheets && this.externalStyleSheets.length > 0) {
            this.externalStyleSheets = externalStyleSheets.split(",");
        } else {
            this.externalStyleSheets = [];
        }
    };

    ns.StyledTextEditor.prototype = Object.create(ns.CFMEditor.prototype);

    ns.StyledTextEditor.prototype.start = function() {
        this.$formViewContainer.removeClass("hidden");
        this.$editable = this.$formViewContainer.find(this.options.selectorForEditable);
        this.$editable.data("config", $.extend(true, {}, defaultCFMRTEConfig));
        var self = this;
        if (this.options.customStart) {
            this.$editable.on("rte-start", function() {
                if (self.$editable.data("useFixedInlineToolbar")) {
                    self._start();
                }
            });
        } else {
            if (this.$editable.data("useFixedInlineToolbar")) {
                this._start();
            }
        }
    };

    ns.StyledTextEditor.prototype._start = function() {
        var rtePluginsDefaults, configCallBack, index, $styleSheet, self = this;
        var rteOptions = {
            "element": self.$editable,
            "componentType": self.editorType,
            "preventCaretInitialize": true
        };
        var preferredTbType = this.$editable.data("preferredTbType");
        if (preferredTbType) {
            rteOptions["listeners"] = {};
            rteOptions["listeners"]["onStarted"] = function() {
                var ek = self.rte.editorKernel;
                if (!ek.hasBackgroundToolbar(preferredTbType)) {
                    ek.addBackgroundToolbar({
                        "tbType": preferredTbType,
                        "isSticky": true
                    });
                }
                ek.setActiveToolbar(preferredTbType);
            }
        }
        this._pushValue();
        if (this.editorType == "table") {
            rtePluginsDefaults = {
                "useColPercentage": false,
                    "rtePlugins": {
                        "table": {
                            "features": "*",
                            "defaultValues": {
                            "width": "100%"
                        },
                        "editMode": CUI.rte.plugins.TablePlugin.EDITMODE_TABLE
                    }
                }
            };
            configCallBack = function(config) {
                return Granite.Util.applyDefaults({}, rtePluginsDefaults, config);
            };
        }
        if (this.options.$rteToolbarContainer) {
            rteOptions["$ui"] = this.options.$rteToolbarContainer;
        }
        this.rte = new CUI.RichText(rteOptions);
        // add external style sheets to <head> element if not already present
        for (index = 0; index < this.externalStyleSheets.length; index++) {
            $styleSheet = $("head link[href='" + externalStyleSheets[index] +"']");
            if ($styleSheet.length <= 0) {
                $styleSheet = $("<link rel=\"stylesheet\" href=\"" + externalStyleSheets[index] + "\" type=\"text/css\">");
                $("head").append($styleSheet);
                this._styleElements.push($styleSheet);
            }
        }
        if (!$("#Editor").data("isReadOnly")) {
            this._initializeEventHandling();
            CUI.rte.ConfigUtils.loadConfigAndStartEditing(this.rte, self.$editable, configCallBack);
        }
    };

    ns.StyledTextEditor.prototype._initializeEventHandling = function() {
        var self = this;
        if (this.options.disableToolbarOnStart) {
            self.$editable.on("editing-start.styledEditor", function() {
                self.rte.editorKernel.disableToolbar();
            });
        }
        this.$editable.on("change.styledEditor", function() {
            self._syncValue();
            channel.trigger(ns.constants.EVENT_CONTENT_FRAGMENT_FIELD_MODIFIED);
        });
        this.$editable.on("focus.styledEditor", function(e) {
            self._triggerListeners.call(self, "cfm-editor-focus", e);
        });
        this.$editable.on("blur.styledEditor", function(e) {
            self._triggerListeners.call(self, "cfm-editor-blur", e);
        });
    };

    ns.StyledTextEditor.prototype.focus = function() {
        this.$editable.focus();
    };

    ns.StyledTextEditor.prototype._finalizeEventHandling = function() {
        this.$editable.off("editing-start.styledEditor");
        this.$editable.off("change.styledEditor");
        this.$editable.off("focus.styledEditor");
        this.$editable.off("blur.styledEditor");
    };

    ns.StyledTextEditor.prototype.adaptToContext = function(context) {
        if (context.undoConfig) {
            this.rte.setUndoConfig(context.undoConfig);
        }
        if (context.bkm) {
            CUI.rte.Selection.selectBookmark(this.rte.editorKernel.getEditContext(), context.bkm);
        }
    };

    ns.StyledTextEditor.prototype.getEditorAdapter = function() {
        if (!this.rteFullScreenAdapter) {
            this.rteFullScreenAdapter = new ns.RTEAdapter(this.rte);
        }
        return this.rteFullScreenAdapter;
    };
    
    ns.StyledTextEditor.prototype.end = function() {
        // todo do we need to un-initialize the member variables here, so that other methods don't work after finish ?
        var index;
        this._syncValue();
        this._finalizeEventHandling();
        this.removeAllEventListeners();
        this.rte.finish(false);
        for (index = 0; index < this._styleElements.length; index++) {
            this._styleElements[index].remove();
        }
        // todo doesn't look nice to remove here as its added by loadConfigAndStartEditing
        this.$editable.removeData("rteinstance");
        this.$formViewContainer.addClass("hidden");
        this.$editable.off("rte-start");
    };

    /**
     * Sync value from editable to text field.
     * @private
     */
    ns.StyledTextEditor.prototype._syncValue = function() {
        this.$textField.val(this.rte.getContent());
    };

    /**
     * Push value from text field to editable.
     * @private
     */
    ns.StyledTextEditor.prototype._pushValue = function() {
        this.$editable.empty().append(this.$textField.val());
    };

    ns.StyledTextEditor.prototype.getMimeType = function() {
        return "text/html";
    };

    ns.StyledTextEditor.prototype.getValue = function() {
        return this.rte.getContent();
    };

    ns.StyledTextEditor.prototype.setValue = function(value) {
        if (this.rte) {
            // reinitialize change state
            var context = this.rte.editorKernel.getEditContext();
            context.setState("DAM.CFM.dirtyHTMLState", false);
            context.setState("DAM.CFM.deferred", 0);
            context.setState("DAM.CFM.skipDirtyCheck", false);
            this.rte.setContent(value);
            ns.editor.Core.notifyModification(undefined, {
                editor: this,
                initial: true
            });
            this._initialValue = undefined;
        } else {
            this._initialValue = value;
        }
        channel.trigger(ns.constants.EVENT_CONTENT_FRAGMENT_FIELD_MODIFIED);

    };

    ns.StyledTextEditor.prototype.getPlainText = function() {
        return this.htmlExtractor.extract(this.$editable);
    };

    ns.StyledTextEditor.prototype.hasToolbar = function() {
        return true;
    };

})($, window.Dam.CFM, window);

pFB css code

/*************************************************************************
 * ADOBE CONFIDENTIAL
 * ___________________
 * 
 *  Copyright 2017 Adobe
 *  All Rights Reserved.
 * 
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe and its suppliers, if any. The intellectual
 * and technical concepts contained herein are proprietary to Adobe
 * and its suppliers and are protected by all applicable intellectual
 * property laws, including trade secret and copyright laws.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe.
 *************************************************************************/
 
#Editor {
    overflow-y: auto;
}

.cfm-Form {
    min-width: 460px;
}

coral-checkbox {
    flex-wrap:wrap;
}

coral-checkbox::after{
    content:'';	
    width: 100%;
}

coral-checkbox .coral-Form-errorlabel{	
    order: 1;
}

span.strikethrough {
    text-decoration:line-through;
    text-decoration-thickness:2px;
    text-decoration-color: red;
    text-decoration-style:solid;
}

 

pfb how i have created the client-lib

rajat168_0-1718349744739.png

 

Avatar

Community Advisor

Hi @rajat168 
Thanks for sharing it, it seems you are using OOTB Style RTE plugin, which adding span with classes

"styles": {
            "features": "*",
            "styles": {
              "strikethrough": {
            "text": "StrikeThrough",
            "cssName": "strikethrough"
				}             
            }
          },

 



Arun Patidar

Avatar

Level 3

as i analyzed, these are all the HTML tags supported, we dont have strickthrough html tag

rajathannasi_0-1718353527225.png

package com.adobe.cq.ui.wcm.commons.internal.services;

import com.adobe.cq.ui.wcm.commons.HtmlToJsonContext;
import com.adobe.cq.ui.wcm.commons.HtmlToJsonConvertor;
import com.adobe.cq.ui.wcm.commons.LinkHandler;
import com.adobe.granite.toggle.api.ToggleRouter;
import com.day.cq.dam.api.Asset;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.NodeVisitor;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

@Component(service = {HtmlToJsonConvertor.class})
public class HtmlToJsonConvertorImpl implements HtmlToJsonConvertor {
  public static final String PN_CONTENT = "content";
  
  public static final String PN_DATA = "data";
  
  public static final String PN_NODE_TYPE = "nodeType";
  
  public static final String PN_VALUE = "value";
  
  public static final String PN_FORMAT = "format";
  
  public static final String PN_VARIANTS = "variants";
  
  public static final String PN_PATH = "path";
  
  public static final String PN_MIMETYPE = "mimetype";
  
  public static final String PN_STYLE = "style";
  
  public static final String FT_LINKS_MARKUP_FIX = "FT_SITES-6428";
  
  @Reference
  private ToggleRouter toggleRouter;
  
  private enum HTMLTags {
    H1("H1", "h1"),
    H2("H2", "h2"),
    H3("H3", "h3"),
    H4("H4", "h4"),
    H5("H5", "h5"),
    H6("H6", "h6"),
    HR("HR", "hr"),
    A("A", "link"),
    P("P", "paragraph"),
    BR("BR", "line-break"),
    SPAN("SPAN", "span"),
    TABLE("TABLE", "table"),
    TBODY("TBODY", "table-body"),
    TR("TR", "table-row"),
    TH("TH", "table-head"),
    TD("TD", "table-data"),
    UL("UL", "unordered-list"),
    OL("OL", "ordered-list"),
    LI("LI", "list-item"),
    IMG("IMG", "image"),
    NOT_SUPPORTED("", ""),
    B("B", "bold"),
    U("U", "underline"),
    STRONG("STRONG", "strong"),
    I("I", "italic"),
    EM("EM", "emphasis"),
    PRE("PRE", "pre"),
    CODE("CODE", "code");
    
    private String tag;
    
    private String blockType;
    
    static final EnumSet<HTMLTags> headerList = EnumSet.range(H1, H6);
    
    static final EnumSet<HTMLTags> blockList = EnumSet.range(H1, LI);
    
    static final EnumSet<HTMLTags> skipBlankTextForFirstChild = EnumSet.of(H1, new HTMLTags[] { 
          H2, H3, H4, H5, H6, P, UL, OL, LI, PRE, 
          TABLE, TBODY, TR, TD, TH, IMG, A });
    
    static final EnumSet<HTMLTags> skipBlankTextAfterStructureFinished = EnumSet.of(H1, new HTMLTags[] { 
          H2, H3, H4, H5, H6, P, UL, OL, LI, PRE, 
          TABLE, TBODY, TR, TD, TH, IMG, A, BR });
    
    static final EnumSet<HTMLTags> formattingList = EnumSet.range(B, CODE);
    
    HTMLTags(String tag, String blockType) {
      this.tag = tag;
      this.blockType = blockType;
    }
    
    static {
    
    }
    
    public boolean isHeader() {
      return headerList.contains(this);
    }
    
    public boolean isBlock() {
      return blockList.contains(this);
    }
    
    public boolean skipBlankTextForFirstChild() {
      return skipBlankTextForFirstChild.contains(this);
    }
    
    public boolean skipBlankTextAfterStructureFinished() {
      return skipBlankTextAfterStructureFinished.contains(this);
    }
    
    public boolean isFormatting() {
      return formattingList.contains(this);
    }
    
    public String toString() {
      return this.tag;
    }
    
    public String getBlockType() {
      return this.blockType;
    }
    
    public static HTMLTags getByName(String tagName) {
      HTMLTags tag;
      try {
        tag = valueOf(tagName.toUpperCase());
      } catch (IllegalArgumentException e) {
        tag = NOT_SUPPORTED;
      } 
      return tag;
    }
  }
  
  private static class Html2JsonVisitor implements NodeVisitor {
    private final HtmlToJsonContext context;
    
    private final JsonArray result = new JsonArray();
    
    private final Deque<JsonObject> currentParentBlocks = new ArrayDeque<>();
    
    private final List<String> currentMarks = new ArrayList<>();
    
    private final Map<String, String> currentStyles = new HashMap<>();
    
    private final Map<String, String> attributes = new HashMap<>();
    
    private boolean skipBlankText;
    
    private final boolean fixLinksMarkup;
    
    private Html2JsonVisitor(HtmlToJsonContext context, boolean fixLinksMarkup) {
      this.context = context;
      this.skipBlankText = true;
      this.fixLinksMarkup = fixLinksMarkup;
    }
    
    public JsonArray getJson() {
      return this.result;
    }
    
    private Map<String, String> toAttributeMap(Attributes attributes) {
      Map<String, String> attributeMap = new HashMap<>(4);
      for (Attribute attrib : attributes)
        attributeMap.put(attrib.getKey(), attrib.getValue()); 
      return attributeMap;
    }
    
    private JsonElement getJsonValue(Object data) {
      if (data instanceof List) {
        JsonArray array = new JsonArray();
        List<?> list = (List)data;
        for (Object item : list)
          array.add(getJsonValue(item)); 
        return (JsonElement)array;
      } 
      if (data instanceof Map) {
        JsonObject obj = new JsonObject();
        Map<String, ?> map = (Map<String, ?>)data;
        map.forEach((key, value) -> obj.add(key, getJsonValue(value)));
        return (JsonElement)obj;
      } 
      if (data instanceof Boolean)
        return (JsonElement)new JsonPrimitive((Boolean)data); 
      if (data instanceof String)
        return (JsonElement)new JsonPrimitive((String)data); 
      if (data instanceof Number)
        return (JsonElement)new JsonPrimitive((Number)data); 
      if (data instanceof Character)
        return (JsonElement)new JsonPrimitive((Character)data); 
      throw new IllegalStateException("Unsupported primitive: " + data
          .getClass().getName());
    }
    
    private void addToJsonObject(JsonObject object, Map<String, Object> data) {
      data.forEach((key, value) -> object.add(key, getJsonValue(value)));
    }
    
    private LinkHandler getLinkHandler(Map<String, String> attribs) {
      for (LinkHandler handler : this.context.getLinkHandlers()) {
        if (handler.isApplicable(attribs, this.context))
          return handler; 
      } 
      return null;
    }
    
    private void handleAttributes(JsonObject block, LinkHandler handler, Map<String, String> attribMap) {
      if (!this.attributes.isEmpty()) {
        JsonObject attributeObj = new JsonObject();
        Objects.requireNonNull(attributeObj);
        this.attributes.forEach(attributeObj::addProperty);
        if (Objects.nonNull(handler)) {
          Map<String, Object> data = handler.createLinkData(attribMap, this.context);
          addToJsonObject(attributeObj, data);
        } 
        block.add("data", (JsonElement)attributeObj);
      } 
    }
    
    private void addBlockObject(JsonObject block) {
      if (this.currentParentBlocks.isEmpty()) {
        this.result.add((JsonElement)block);
      } else {
        JsonObject headEl = this.currentParentBlocks.peek();
        JsonArray jsonArray = headEl.getAsJsonArray("content");
        if (jsonArray == null) {
          headEl.add("content", (JsonElement)block);
        } else {
          jsonArray.add((JsonElement)block);
        } 
      } 
      this.currentParentBlocks.push(block);
    }
    
    private void appendBlock(HtmlToJsonConvertorImpl.HTMLTags tag, Element element) {
      JsonObject block = new JsonObject();
      LinkHandler handler = null;
      Map<String, String> attribMap = null;
      block.addProperty("nodeType", tag.getBlockType());
      if (tag.isHeader()) {
        block.addProperty("nodeType", "header");
        block.addProperty("style", tag.blockType);
      } else if (tag == HtmlToJsonConvertorImpl.HTMLTags.A) {
        Attributes attributes = element.attributes();
        if (attributes.hasKey("href")) {
          attribMap = toAttributeMap(attributes);
          handler = getLinkHandler(attribMap);
          String type = Objects.nonNull(handler) ? handler.getLinkType(attribMap, this.context) : "link";
          block.addProperty("nodeType", type);
        } else {
          block.addProperty("nodeType", "reference");
        } 
      } 
      if (tag != HtmlToJsonConvertorImpl.HTMLTags.A || this.fixLinksMarkup)
        block.add("content", (JsonElement)new JsonArray()); 
      handleAttributes(block, handler, attribMap);
      JsonObject format = new JsonObject();
      if (!this.currentStyles.isEmpty()) {
        Objects.requireNonNull(format);
        this.currentStyles.forEach(format::addProperty);
      } 
      if (format.size() != 0)
        block.add("format", (JsonElement)format); 
      addBlockObject(block);
    }
    
    private String preprocessText(String text) {
      if (this.skipBlankText && StringUtils.isBlank(text))
        return null; 
      return text.isEmpty() ? null : text;
    }
    
    private void appendText(String text) {
      text = preprocessText(text);
      if (text == null)
        return; 
      JsonObject current = new JsonObject();
      current.addProperty("nodeType", "text");
      current.addProperty("value", text);
      JsonObject format = new JsonObject();
      if (!this.currentMarks.isEmpty()) {
        JsonArray marks = new JsonArray();
        Objects.requireNonNull(marks);
        this.currentMarks.forEach(marks::add);
        format.add("variants", (JsonElement)marks);
      } 
      if (format.size() != 0)
        current.add("format", (JsonElement)format); 
      if (this.currentParentBlocks.isEmpty()) {
        this.result.add((JsonElement)current);
        return;
      } 
      JsonObject headEl = this.currentParentBlocks.peek();
      if (headEl.has("content") && headEl.get("content").isJsonArray()) {
        headEl.getAsJsonArray("content").add((JsonElement)current);
      } else {
        boolean applyFormatting = !headEl.has("value");
        String newValue = headEl.has("value") ? (headEl.get("value").getAsString() + text) : text;
        headEl.addProperty("value", newValue);
        if (applyFormatting && format.size() != 0 && !headEl.has("format"))
          headEl.add("format", (JsonElement)format); 
      } 
    }
    
    private void appendImage(Element element) {
      String src=element.attributes().get("src");
      ResourceResolver resolver = this.context.getResourceResolver();
      Resource assetResource = (resolver != null) ? resolver.getResource(src) : null;
      Asset asset = Objects.nonNull(assetResource) ? (Asset)assetResource.adaptTo(Asset.class) : null;
      if (Objects.nonNull(asset)) {
        JsonObject current = new JsonObject();
        current.addProperty("nodeType", "reference");
        JsonObject data = new JsonObject();
        data.addProperty("path", src);
        data.addProperty("mimetype", asset.getMimeType());
        current.add("data", (JsonElement)data);
        if (this.currentParentBlocks.isEmpty()) {
          this.result.add((JsonElement)current);
        } else {
          JsonObject headEl = this.currentParentBlocks.peek();
          JsonArray jsonArray = headEl.getAsJsonArray("content");
          if (jsonArray == null) {
            headEl.add("content", (JsonElement)current);
          } else {
            jsonArray.add((JsonElement)current);
          } 
        } 
      } 
    }
    
    private void appendMark(HtmlToJsonConvertorImpl.HTMLTags tag) {
      this.currentMarks.add(tag.getBlockType());
    }
    
    private void appendAttributes(Element element, boolean isFormatTag) {
      if (!isFormatTag) {
        this.currentStyles.clear();
        this.attributes.clear();
      } 
      element.attributes().asList().forEach(elem -> {
            if (StringUtils.equals("style", elem.getKey())) {
              Arrays.<String>stream(elem.getValue().split(";")).forEach(());
            } else {
              this.attributes.put(elem.getKey(), elem.getValue());
            } 
          });
    }
    
    private void popBlock() {
      if (!this.currentParentBlocks.isEmpty())
        this.currentParentBlocks.pop(); 
    }
    
    private void popAttributes() {
      this.currentStyles.clear();
      this.attributes.clear();
    }
    
    private void popMark(HtmlToJsonConvertorImpl.HTMLTags tag) {
      this.currentMarks.remove(tag.getBlockType());
    }
    
    public void head(Node node, int depth) {
      if (node instanceof TextNode) {
        TextNode textNode = (TextNode)node;
        appendText(textNode.text());
        this.skipBlankText = false;
      } else if (node instanceof Element) {
        Element element = (Element)node;
        HtmlToJsonConvertorImpl.HTMLTags tagName = HtmlToJsonConvertorImpl.HTMLTags.getByName(element.tagName());
        if (tagName.isBlock()) {
          appendAttributes(element, false);
          appendBlock(tagName, element);
        } else if (tagName.isFormatting()) {
          appendAttributes(element, true);
          appendMark(tagName);
        } else if (tagName == HtmlToJsonConvertorImpl.HTMLTags.IMG) {
          appendImage(element);
        } 
        this.skipBlankText = tagName.skipBlankTextForFirstChild();
      } 
    }
    
    public void tail(Node node, int depth) {
      if (node instanceof Element) {
        Element element = (Element)node;
        HtmlToJsonConvertorImpl.HTMLTags tagName = HtmlToJsonConvertorImpl.HTMLTags.getByName(element.tagName());
        if (tagName.isBlock()) {
          popBlock();
          popAttributes();
        } else if (tagName.isFormatting()) {
          popMark(tagName);
        } 
        this.skipBlankText = tagName.skipBlankTextAfterStructureFinished();
      } 
    }
  }
  
  public String convert(String html) {
    return convert(html, createContext());
  }
  
  public String convert(String html, ResourceResolver resourceResolver) {
    HtmlToJsonContext context = createContext();
    context.setResourceResolver(resourceResolver);
    return convert(html, context);
  }
  
  public HtmlToJsonContext createContext() {
    return new HtmlToJsonContextImpl();
  }
  
  public String convert(String html, HtmlToJsonContext context) {
    context = (context != null) ? context : new HtmlToJsonContextImpl();
    Document doc = Jsoup.parse(html, StandardCharsets.UTF_8.name());
    boolean fixLinkMarkup = (this.toggleRouter != null && this.toggleRouter.isEnabled("FT_SITES-6428"));
    Html2JsonVisitor visitor = new Html2JsonVisitor(context, fixLinkMarkup);
    doc.traverse(visitor);
    return visitor.getJson().toString();
  }
}

@arunpatidar  @h_kataria  fyi

Avatar

Level 4

As Arun mentioned, this is because of the way strikethrough plugin is implemented on your side. If it is span tag, then you are bound to get span in the json representation along with the class in data key and as far as I know, I don't think there will be any easy way to change that JSON structure but I think the Front end layer which is consuming that json can easily adapt logic to use the "strikethrough" class which you have implemented.
You can also check if you pass your description as html instead of json in your query which can be consumed rather easily compared to the json.

description {
  html
}