protected internalRender()

in source/nodejs/adaptivecards/src/card-elements.ts [1070:1259]


    protected internalRender(): HTMLElement | undefined {
        this._processedText = undefined;

        if (this.text) {
            const preProcessedText = this.preProcessPropertyValue(BaseTextBlock.textProperty);
            const hostConfig = this.hostConfig;

            let element: HTMLElement;

            if (this.forElementId) {
                const labelElement = document.createElement("label");
                labelElement.htmlFor = this.forElementId;

                element = labelElement;
            } else {
                element = document.createElement("div");
            }

            element.classList.add(hostConfig.makeCssClassName("ac-textBlock"));
            element.style.overflow = "hidden";

            this.applyStylesTo(element);

            if (this.style === "heading") {
                element.setAttribute("role", "heading");

                const headingLevel = this.hostConfig.textBlock.headingLevel;

                if (headingLevel !== undefined && headingLevel > 0) {
                    element.setAttribute("aria-level", headingLevel.toString());
                }
            }

            if (this.selectAction && hostConfig.supportsInteractivity) {
                element.onclick = (e) => {
                    if (this.selectAction && this.selectAction.isEnabled) {
                        e.preventDefault();
                        e.cancelBubble = true;

                        this.selectAction.execute();
                    }
                };

                this.selectAction.setupElementForAccessibility(element);

                if (this.selectAction.isEnabled) {
                    element.classList.add(hostConfig.makeCssClassName("ac-selectable"));
                }
            }

            if (!this._processedText) {
                this._treatAsPlainText = true;

                let formattedText = TextFormatters.formatText(this.lang, preProcessedText);

                if (this.useMarkdown && formattedText) {
                    if (GlobalSettings.allowMarkForTextHighlighting) {
                        formattedText = formattedText
                            .replace(/<mark>/g, "===")
                            .replace(/<\/mark>/g, "/==/");
                    }

                    const markdownProcessingResult = AdaptiveCard.applyMarkdown(formattedText);

                    if (
                        markdownProcessingResult.didProcess &&
                        markdownProcessingResult.outputHtml
                    ) {
                        this._processedText = markdownProcessingResult.outputHtml;
                        this._treatAsPlainText = false;

                        // Only process <mark> tag if markdown processing was applied because
                        // markdown processing is also responsible for sanitizing the input string
                        if (GlobalSettings.allowMarkForTextHighlighting && this._processedText) {
                            let markStyle: string = "";
                            const effectiveStyle = this.getEffectiveStyleDefinition();

                            if (effectiveStyle.highlightBackgroundColor) {
                                markStyle +=
                                    "background-color: " +
                                    effectiveStyle.highlightBackgroundColor +
                                    ";";
                            }

                            if (effectiveStyle.highlightForegroundColor) {
                                markStyle +=
                                    "color: " + effectiveStyle.highlightForegroundColor + ";";
                            }

                            if (markStyle) {
                                markStyle = 'style="' + markStyle + '"';
                            }

                            this._processedText = this._processedText
                                .replace(/===/g, "<mark " + markStyle + ">")
                                .replace(/\/==\//g, "</mark>");
                        }
                    } else {
                        this._processedText = formattedText;
                        this._treatAsPlainText = true;
                    }
                } else {
                    this._processedText = formattedText;
                    this._treatAsPlainText = true;
                }
            }

            if (!this._processedText) {
                this._processedText = "";
            }

            if (this._treatAsPlainText) {
                element.innerText = this._processedText;
            } else {
                element.innerHTML = this._processedText;
            }

            if (element.firstElementChild instanceof HTMLElement) {
                const firstElementChild = element.firstElementChild;
                firstElementChild.style.marginTop = "0px";
                firstElementChild.style.width = "100%";

                if (!this.wrap) {
                    firstElementChild.style.overflow = "hidden";
                    firstElementChild.style.textOverflow = "ellipsis";
                }
            }

            if (element.lastElementChild instanceof HTMLElement) {
                element.lastElementChild.style.marginBottom = "0px";
            }

            const anchors = element.getElementsByTagName("a");

            for (const anchor of Array.from(anchors)) {
                anchor.classList.add(hostConfig.makeCssClassName("ac-anchor"));
                anchor.target = "_blank";
                anchor.onclick = (e: MouseEvent) => {
                    if (raiseAnchorClickedEvent(this, anchor, e)) {
                        e.preventDefault();
                        e.cancelBubble = true;
                    }
                };
                anchor.oncontextmenu = (e: MouseEvent) => {
                    if (raiseAnchorClickedEvent(this, anchor, e)) {
                        e.preventDefault();
                        e.cancelBubble = true;

                        return false;
                    }

                    return true;
                };
            }

            if (this.wrap) {
                element.style.wordWrap = "break-word";

                if (this.maxLines && this.maxLines > 0) {
                    element.style.overflow = "hidden";

                    if (Utils.isInternetExplorer() || !GlobalSettings.useWebkitLineClamp) {
                        element.style.maxHeight = this._computedLineHeight * this.maxLines + "px";
                    } else {
                        // While non standard, --webkit-line-clamp works in every browser (except IE)
                        // and is a great solution to support the maxLines feature with ellipsis
                        // truncation. With --webkit-line-clamp there is need to use explicit line heights
                        element.style.removeProperty("line-height");
                        element.style.display = "-webkit-box";
                        element.style.webkitBoxOrient = "vertical";
                        element.style.webkitLineClamp = this.maxLines.toString();
                    }
                }
            } else {
                element.style.whiteSpace = "nowrap";
                element.style.textOverflow = "ellipsis";
            }

            if (
                GlobalSettings.useAdvancedTextBlockTruncation ||
                GlobalSettings.useAdvancedCardBottomTruncation
            ) {
                this._originalInnerHtml = element.innerHTML;
            }

            return element;
        } else {
            return undefined;
        }
    }