@WorkerThread
        private static Pair<CharSequence, Boolean> createDescriptionContentHelper(final Activity activity, final String descriptionText, final boolean textTooLong, final int descriptionFullLength, final Geocache cache, final boolean restrictLength, final TextView descriptionView, final HtmlStyle descriptionStyle) {
            try {
                //Format to HTML. This takes time on long listings or those with e.g. many images...
                final HtmlImage imageGetter = new HtmlImage(cache.getGeocode(), true, false, descriptionView, false);
                final Pair<Spannable, Boolean> renderedHtml = descriptionStyle.render(activity, descriptionText, imageGetter::getDrawable);
                final SpannableStringBuilder description = new SpannableStringBuilder(renderedHtml.first);
                final boolean renderError = renderedHtml.second;

                if (StringUtils.isNotBlank(description)) {
                    handleImageClick(activity, cache, description);
                    WherigoViewUtils.htmlReplaceWherigoClickAction(activity, cache.getGeocode(), description);
                    //display various fixes
                    HtmlUtils.fixRelativeLinks(description, ConnectorFactory.getConnector(cache).getHostUrl() + "/");
                    fixOldGeocheckerLink(activity, cache, description);
                }

                // If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
                // Technically, it may not be a table, but a pre, which has the same problems as a table, so the message is ok even though
                // sometimes technically incorrect.
                if (renderError) {
                    final IConnector connector = ConnectorFactory.getConnector(cache);
                    if (StringUtils.isNotEmpty(cache.getUrl())) {
                        final Spanned tableNote = HtmlCompat.fromHtml(activity.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"), HtmlCompat.FROM_HTML_MODE_LEGACY);
                        description.append("\n\n").append(TextUtils.setSpan(tableNote, new StyleSpan(Typeface.ITALIC)));
                    }
                }

                //add warning on too-long-listing
                if (textTooLong && restrictLength) {
                    description.append("\n\n")
                            .append(TextParam.id(R.string.cache_description_render_restricted_warning, descriptionFullLength, DESCRIPTION_MAX_SAFE_LENGTH * 100 / descriptionFullLength).getText(null), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }

                return new Pair<>(description, textTooLong && restrictLength);
            } catch (final RuntimeException re) {
                Log.e("Problems parsing cache description", re);
                return new Pair<>(activity.getString(R.string.err_load_descr_failed) + ": " + re.getMessage(), false);
            }
        }
CALL IN BACKGROUND ONLY! Renders cache description into an Editable.
main/src/main/java/cgeo/geocaching/CacheDetailActivity.java