IDEA-342771 Rename QuickDocCodeHighlightingHelper to QuickDocHighlightingHelper, improve API and add JavaDoc

GitOrigin-RevId: 412d6ec56fc0f08a4383f03357f9b93fa0ef2698
This commit is contained in:
Piotr Tomiak
2024-01-24 11:38:11 +01:00
committed by intellij-monorepo-bot
parent fa7bfe0a4b
commit 6140fd9910
22 changed files with 407 additions and 270 deletions

View File

@@ -83,7 +83,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.intellij.codeInsight.javadoc.SnippetMarkup.*;
import static com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.*;
import static com.intellij.lang.documentation.QuickDocHighlightingHelper.*;
public class JavaDocInfoGenerator {

View File

@@ -61,7 +61,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledSignatureFragment;
import static com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledSignatureFragment;
import static com.intellij.util.ObjectUtils.notNull;
/**

View File

@@ -1,7 +1,7 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.documentation;
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper;
import com.intellij.lang.documentation.QuickDocHighlightingHelper;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.module.ModuleType;
@@ -92,7 +92,7 @@ public final class DocumentationHtmlUtil {
// Styled code
EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme();
result.addAll(QuickDocCodeHighlightingHelper.getDefaultDocCodeStyles(globalScheme, background));
result.addAll(QuickDocHighlightingHelper.getDefaultDocCodeStyles(globalScheme, background));
return result;
}

View File

@@ -7,7 +7,7 @@ import com.intellij.codeInsight.documentation.DocumentationActionProvider;
import com.intellij.codeInsight.documentation.DocumentationComponent;
import com.intellij.icons.AllIcons;
import com.intellij.ide.ui.UISettings;
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper;
import com.intellij.lang.documentation.QuickDocHighlightingHelper;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -385,7 +385,7 @@ public final class DocRenderer implements CustomFoldRegionRenderer {
".section {padding-right: 5; white-space: nowrap}" +
".content {padding: 2 0 2 0}" +
(useTipsKit ? createAdditionalStylesForTips(editor) : "") +
StringUtil.join(QuickDocCodeHighlightingHelper.getDefaultDocCodeStyles(
StringUtil.join(QuickDocHighlightingHelper.getDefaultDocCodeStyles(
colorsScheme, colorsScheme.getDefaultBackground()), "\n");
StyleSheet result = StyleSheetUtil.loadStyleSheet(input);
if (!useTipsKit) {

View File

@@ -1,186 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.lang.documentation
import com.intellij.ide.ui.html.StyleSheetRulesProviderForCodeHighlighting
import com.intellij.lang.Language
import com.intellij.lang.documentation.DocumentationSettings.InlineCodeHighlightingMode
import com.intellij.openapi.editor.colors.EditorColorsScheme
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.DefaultProjectFactory
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.xml.util.XmlStringUtil
import java.awt.Color
object QuickDocCodeHighlightingHelper {
const val CODE_BLOCK_PREFIX = StyleSheetRulesProviderForCodeHighlighting.CODE_BLOCK_PREFIX
const val CODE_BLOCK_SUFFIX = StyleSheetRulesProviderForCodeHighlighting.CODE_BLOCK_SUFFIX
const val INLINE_CODE_PREFIX = StyleSheetRulesProviderForCodeHighlighting.INLINE_CODE_PREFIX
const val INLINE_CODE_SUFFIX = StyleSheetRulesProviderForCodeHighlighting.INLINE_CODE_SUFFIX
@JvmStatic
fun getStyledCodeBlock(code: @NlsSafe CharSequence, language: Language?, project: Project? = null): @NlsSafe String =
StringBuilder().apply { appendStyledCodeBlock(code, language, project) }.toString()
@JvmStatic
fun StringBuilder.appendStyledCodeBlock(code: @NlsSafe CharSequence,
language: Language?,
project: Project? = null): @NlsSafe StringBuilder =
append(CODE_BLOCK_PREFIX)
.appendHighlightedCode(DocumentationSettings.isHighlightingOfCodeBlocksEnabled(), code, language, project, true)
.append(CODE_BLOCK_SUFFIX)
@JvmStatic
fun removeSurroundingStyledCodeBlock(string: String): String =
string.trim().removeSurrounding(CODE_BLOCK_PREFIX, CODE_BLOCK_SUFFIX)
@JvmStatic
@JvmOverloads
fun getStyledInlineCode(@NlsSafe code: String, language: Language? = null, project: Project? = null): @NlsSafe String =
StringBuilder().apply { appendStyledInlineCode(code, language, project) }.toString()
@JvmStatic
@JvmOverloads
fun StringBuilder.appendStyledInlineCode(@NlsSafe code: String, language: Language? = null, project: Project? = null): StringBuilder =
append(INLINE_CODE_PREFIX)
.appendHighlightedCode(
DocumentationSettings.getInlineCodeHighlightingMode() == InlineCodeHighlightingMode.SEMANTIC_HIGHLIGHTING, code, language, project,
true)
.append(INLINE_CODE_SUFFIX)
@JvmStatic
@JvmOverloads
fun getStyledInlineCodeFragment(code: String, language: Language? = null, project: Project? = null): String =
StringBuilder().apply { appendStyledInlineCodeFragment(code, language, project) }.toString()
@JvmStatic
@JvmOverloads
fun StringBuilder.appendStyledInlineCodeFragment(code: String, language: Language? = null, project: Project? = null): StringBuilder =
appendHighlightedCode(true, code, language, project, false)
@JvmStatic
fun StringBuilder.appendStyledLinkFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(DocumentationSettings.isSemanticHighlightingOfLinksEnabled(), textAttributes,
contents, false)
@JvmStatic
fun StringBuilder.appendStyledLinkFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(DocumentationSettings.isSemanticHighlightingOfLinksEnabled(), textAttributesKey,
contents, false)
@JvmStatic
fun StringBuilder.appendStyledSignatureFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled(), textAttributes,
contents, false)
@JvmStatic
fun StringBuilder.appendStyledSignatureFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled(), textAttributesKey,
contents, false)
@JvmStatic
fun StringBuilder.appendStyledFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(true, textAttributes, contents, false)
@JvmStatic
fun StringBuilder.appendStyledFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(true, textAttributesKey, contents, false)
@JvmStatic
fun StringBuilder.appendWrappedWithInlineCodeTag(@NlsSafe contents: CharSequence): @NlsSafe StringBuilder =
if (!contents.isBlank())
append(INLINE_CODE_PREFIX, contents, INLINE_CODE_SUFFIX)
else
this
@JvmStatic
fun StringBuilder.wrapWithInlineCodeTag(): @NlsSafe StringBuilder =
if (!isBlank())
insert(0, INLINE_CODE_PREFIX)
.append(INLINE_CODE_SUFFIX)
else
this
@JvmStatic
fun wrapWithInlineCodeTag(string: String): @NlsSafe String =
if (!string.isBlank())
INLINE_CODE_PREFIX + string + INLINE_CODE_SUFFIX
else
string
@JvmStatic
fun guessLanguage(language: String?): Language? =
if (language == null)
null
else
Language
.findInstancesByMimeType(language)
.asSequence()
.plus(Language.findInstancesByMimeType("text/$language"))
.plus(
Language.getRegisteredLanguages()
.asSequence()
.filter { languageMatches(language, it) }
)
.firstOrNull()
@JvmStatic
fun getDefaultDocCodeStyles(
colorScheme: EditorColorsScheme,
editorPaneBackgroundColor: Color,
): List<String> = StyleSheetRulesProviderForCodeHighlighting.getRules(
colorScheme, editorPaneBackgroundColor,
listOf(".content", ".content-separated", ".content-only div:not(.bottom)", ".sections"),
listOf(".definition code", ".definition pre", ".definition-only code", ".definition-only"),
DocumentationSettings.isCodeBackgroundEnabled()
&& DocumentationSettings.getInlineCodeHighlightingMode() !== InlineCodeHighlightingMode.NO_HIGHLIGHTING,
DocumentationSettings.isCodeBackgroundEnabled()
&& DocumentationSettings.isHighlightingOfCodeBlocksEnabled(),
)
private fun StringBuilder.appendHighlightedCode(doHighlighting: Boolean, code: CharSequence, language: Language?, project: Project?,
isForRenderedDoc: Boolean): StringBuilder {
val trimmedCode = code.toString().trim('\n', '\r').trimIndent().replace(' ', ' ')
if (language != null && doHighlighting) {
HtmlSyntaxInfoUtil.appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
this, project ?: DefaultProjectFactory.getInstance().defaultProject, language, trimmedCode,
DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(trimmedCode))
}
return this
}
private fun StringBuilder.appendStyledSpan(doHighlighting: Boolean, attributesKey: TextAttributesKey,
value: String?, isForRenderedDoc: Boolean): StringBuilder {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(this, attributesKey, value, DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(value))
}
return this
}
private fun StringBuilder.appendStyledSpan(doHighlighting: Boolean, attributes: TextAttributes,
value: String?, isForRenderedDoc: Boolean): StringBuilder {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(this, attributes, value, DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(value))
}
return this
}
private fun languageMatches(langType: String, language: Language): Boolean =
langType.equals(language.id, ignoreCase = true)
|| FileTypeManager.getInstance().getFileTypeByExtension(langType) === language.associatedFileType
}

View File

@@ -0,0 +1,296 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.lang.documentation
import com.intellij.ide.ui.html.StyleSheetRulesProviderForCodeHighlighting
import com.intellij.lang.Language
import com.intellij.lang.documentation.DocumentationSettings.InlineCodeHighlightingMode
import com.intellij.openapi.editor.colors.EditorColorsScheme
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.psi.PsiElement
import com.intellij.util.concurrency.annotations.RequiresReadLock
import com.intellij.xml.util.XmlStringUtil
import org.jetbrains.annotations.ApiStatus.Internal
import java.awt.Color
/**
* This class facilitates generation of highlighted text and code for Quick Documentation.
* It honors [DocumentationSettings], when highlighting code and links.
*/
object QuickDocHighlightingHelper {
const val CODE_BLOCK_PREFIX = StyleSheetRulesProviderForCodeHighlighting.CODE_BLOCK_PREFIX
const val CODE_BLOCK_SUFFIX = StyleSheetRulesProviderForCodeHighlighting.CODE_BLOCK_SUFFIX
const val INLINE_CODE_PREFIX = StyleSheetRulesProviderForCodeHighlighting.INLINE_CODE_PREFIX
const val INLINE_CODE_SUFFIX = StyleSheetRulesProviderForCodeHighlighting.INLINE_CODE_SUFFIX
/**
* The returned code block HTML (prefixed with [CODE_BLOCK_PREFIX] and suffixed with [CODE_BLOCK_SUFFIX])
* has syntax highlighted, if there is language provided and
* [DocumentationSettings.isHighlightingOfCodeBlocksEnabled] is `true`. The code block will
* be rendered with a special background if [DocumentationSettings.isCodeBackgroundEnabled] is `true`.
*/
@JvmStatic
@RequiresReadLock
fun getStyledCodeBlock(project: Project, language: Language?, code: @NlsSafe CharSequence): @NlsSafe String =
StringBuilder().apply { appendStyledCodeBlock(project, language, code) }.toString()
/**
* Appends code block HTML (prefixed with [CODE_BLOCK_PREFIX] and suffixed with [CODE_BLOCK_SUFFIX]),
* which has syntax highlighted, if there is language provided and
* [DocumentationSettings.isHighlightingOfCodeBlocksEnabled] is `true`. The code block will
* be rendered with a special background if [DocumentationSettings.isCodeBackgroundEnabled] is `true`.
*/
@JvmStatic
@RequiresReadLock
fun StringBuilder.appendStyledCodeBlock(project: Project, language: Language?, code: @NlsSafe CharSequence): @NlsSafe StringBuilder =
append(CODE_BLOCK_PREFIX)
.appendHighlightedCode(project, language, DocumentationSettings.isHighlightingOfCodeBlocksEnabled(), code, true)
.append(CODE_BLOCK_SUFFIX)
@JvmStatic
fun removeSurroundingStyledCodeBlock(string: String): String =
string.trim().removeSurrounding(CODE_BLOCK_PREFIX, CODE_BLOCK_SUFFIX)
/**
* The returned inline code HTML (prefixed with [INLINE_CODE_PREFIX] and suffixed with [INLINE_CODE_SUFFIX])
* has syntax highlighted, if there is language provided and
* [DocumentationSettings.getInlineCodeHighlightingMode] is [DocumentationSettings.InlineCodeHighlightingMode.SEMANTIC_HIGHLIGHTING].
* The code block will be rendered with a special background if [DocumentationSettings.isCodeBackgroundEnabled] is `true` and
* [DocumentationSettings.getInlineCodeHighlightingMode] is not [DocumentationSettings.InlineCodeHighlightingMode.NO_HIGHLIGHTING].
*/
@JvmStatic
@RequiresReadLock
fun getStyledInlineCode(project: Project, language: Language?, @NlsSafe code: String): @NlsSafe String =
StringBuilder().apply { appendStyledInlineCode(project, language, code) }.toString()
/**
* Appends inline code HTML (prefixed with [INLINE_CODE_PREFIX] and suffixed with [INLINE_CODE_SUFFIX]),
* which has syntax highlighted, if there is language provided and
* [DocumentationSettings.getInlineCodeHighlightingMode] is [DocumentationSettings.InlineCodeHighlightingMode.SEMANTIC_HIGHLIGHTING].
* The code block will be rendered with a special background if [DocumentationSettings.isCodeBackgroundEnabled] is `true` and
* [DocumentationSettings.getInlineCodeHighlightingMode] is not [DocumentationSettings.InlineCodeHighlightingMode.NO_HIGHLIGHTING].
*/
@JvmStatic
@RequiresReadLock
fun StringBuilder.appendStyledInlineCode(project: Project, language: Language?, @NlsSafe code: String): StringBuilder =
append(INLINE_CODE_PREFIX)
.appendHighlightedCode(
project, language, DocumentationSettings.getInlineCodeHighlightingMode() == InlineCodeHighlightingMode.SEMANTIC_HIGHLIGHTING, code,
true)
.append(INLINE_CODE_SUFFIX)
/**
* Returns an HTML fragment containing [code] highlighted with [language].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
@RequiresReadLock
fun getStyledInlineCodeFragment(project: Project, language: Language, @NlsSafe code: String): @NlsSafe String =
StringBuilder().apply { appendStyledInlineCodeFragment(project, language, code) }.toString()
/**
* Appends an HTML fragment containing [code] highlighted with [language].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
@RequiresReadLock
fun StringBuilder.appendStyledInlineCodeFragment(project: Project, language: Language, @NlsSafe code: String): StringBuilder =
appendHighlightedCode(project, language, true, code, false)
/**
* This method should be used when generating links to PsiElements.
*
* Appends an HTML fragment containing [contents] colored according to [textAttributes]
* if [DocumentationSettings.isSemanticHighlightingOfLinksEnabled] is `true`.
*/
@JvmStatic
fun StringBuilder.appendStyledLinkFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(DocumentationSettings.isSemanticHighlightingOfLinksEnabled(), textAttributes,
contents, false)
/**
* This method should be used when generating links to PsiElements.
*
* Appends an HTML fragment containing [contents] colored according to [textAttributesKey]
* if [DocumentationSettings.isSemanticHighlightingOfLinksEnabled] is `true`.
*/
@JvmStatic
fun StringBuilder.appendStyledLinkFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(DocumentationSettings.isSemanticHighlightingOfLinksEnabled(), textAttributesKey,
contents, false)
/**
* This method should be used when generating Quick Doc element signatures.
*
* Appends an HTML fragment containing [contents] colored according to [textAttributes]
* if [DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled] is `true`.
*/
@JvmStatic
fun StringBuilder.appendStyledSignatureFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled(), textAttributes,
contents, false)
/**
* This method should be used when generating Quick Doc element signatures.
*
* Appends an HTML fragment containing [contents] colored according to [textAttributesKey]
* if [DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled] is `true`.
*/
@JvmStatic
fun StringBuilder.appendStyledSignatureFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled(), textAttributesKey,
contents, false)
/**
* This method should be used when generating Quick Doc element signatures.
*
* Appends an HTML fragment containing containing [code] highlighted with [language]
* if [DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled] is `true`.
*/
@JvmStatic
@RequiresReadLock
fun StringBuilder.appendStyledSignatureFragment(project: Project, language: Language, code: String): StringBuilder =
appendHighlightedCode(project, language, DocumentationSettings.isHighlightingOfQuickDocSignaturesEnabled(), code, false)
/**
* Returns an HTML fragment containing [contents] colored according to [textAttributes].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
fun getStyledFragment(contents: String, textAttributes: TextAttributes): String =
StringBuilder().apply { appendStyledFragment(contents, textAttributes) }.toString()
/**
* Returns an HTML fragment containing [contents] colored according to [textAttributesKey].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
fun getStyledFragment(contents: String, textAttributesKey: TextAttributesKey): String =
StringBuilder().apply { appendStyledFragment(contents, textAttributesKey) }.toString()
/**
* Appends an HTML fragment containing [contents] colored according to [textAttributes].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
fun StringBuilder.appendStyledFragment(contents: String, textAttributes: TextAttributes): StringBuilder =
appendStyledSpan(true, textAttributes, contents, false)
/**
* Appends an HTML fragment containing [contents] colored according to [textAttributesKey].
*
* Should not be used when generating Quick Doc signature or [PsiElement] links.
*/
@JvmStatic
fun StringBuilder.appendStyledFragment(contents: String, textAttributesKey: TextAttributesKey): StringBuilder =
appendStyledSpan(true, textAttributesKey, contents, false)
@JvmStatic
fun StringBuilder.appendWrappedWithInlineCodeTag(@NlsSafe contents: CharSequence): @NlsSafe StringBuilder =
if (!contents.isBlank())
append(INLINE_CODE_PREFIX, contents, INLINE_CODE_SUFFIX)
else
this
@JvmStatic
fun StringBuilder.wrapWithInlineCodeTag(): @NlsSafe StringBuilder =
if (!isBlank())
insert(0, INLINE_CODE_PREFIX)
.append(INLINE_CODE_SUFFIX)
else
this
@JvmStatic
fun wrapWithInlineCodeTag(string: String): @NlsSafe String =
if (!string.isBlank())
INLINE_CODE_PREFIX + string + INLINE_CODE_SUFFIX
else
string
/**
* Tries to guess a registered IDE language based. Useful e.g. for Markdown support
* to figure out a language to render a code block.
*/
@JvmStatic
fun guessLanguage(language: String?): Language? =
if (language == null)
null
else
Language
.findInstancesByMimeType(language)
.asSequence()
.plus(Language.findInstancesByMimeType("text/$language"))
.plus(
Language.getRegisteredLanguages()
.asSequence()
.filter { languageMatches(language, it) }
)
.firstOrNull()
@Internal
@JvmStatic
fun getDefaultDocCodeStyles(
colorScheme: EditorColorsScheme,
editorPaneBackgroundColor: Color,
): List<String> = StyleSheetRulesProviderForCodeHighlighting.getRules(
colorScheme, editorPaneBackgroundColor,
listOf(".content", ".content-separated", ".content-only div:not(.bottom)", ".sections"),
listOf(".definition code", ".definition pre", ".definition-only code", ".definition-only"),
DocumentationSettings.isCodeBackgroundEnabled()
&& DocumentationSettings.getInlineCodeHighlightingMode() !== InlineCodeHighlightingMode.NO_HIGHLIGHTING,
DocumentationSettings.isCodeBackgroundEnabled()
&& DocumentationSettings.isHighlightingOfCodeBlocksEnabled(),
)
private fun StringBuilder.appendHighlightedCode(project: Project, language: Language?, doHighlighting: Boolean,
code: CharSequence, isForRenderedDoc: Boolean): StringBuilder {
val trimmedCode = code.toString().trim('\n', '\r').trimIndent().replace(' ', ' ')
if (language != null && doHighlighting) {
HtmlSyntaxInfoUtil.appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
this, project, language, trimmedCode,
DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(trimmedCode))
}
return this
}
private fun StringBuilder.appendStyledSpan(doHighlighting: Boolean, attributesKey: TextAttributesKey,
value: String?, isForRenderedDoc: Boolean): StringBuilder {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(this, attributesKey, value, DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(value))
}
return this
}
private fun StringBuilder.appendStyledSpan(doHighlighting: Boolean, attributes: TextAttributes,
value: String?, isForRenderedDoc: Boolean): StringBuilder {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(this, attributes, value, DocumentationSettings.getHighlightingSaturation(isForRenderedDoc))
}
else {
append(XmlStringUtil.escapeString(value))
}
return this
}
private fun languageMatches(langType: String, language: Language): Boolean =
langType.equals(language.id, ignoreCase = true)
|| FileTypeManager.getInstance().getFileTypeByExtension(langType) === language.associatedFileType
}

View File

@@ -3,7 +3,7 @@ package com.intellij.openapi.editor.richcopy;
import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.lang.Language;
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper;
import com.intellij.lang.documentation.QuickDocHighlightingHelper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.ColorKey;
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.ui.ColorUtil;
import com.intellij.util.concurrency.annotations.RequiresReadLock;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,20 +36,24 @@ public final class HtmlSyntaxInfoUtil {
private HtmlSyntaxInfoUtil() { }
public static @NotNull String getStyledSpan(@Nullable String value, String @NotNull ... properties) {
return appendStyledSpan(new StringBuilder(), value, properties).toString();
}
/**
* @deprecated Use {@link QuickDocHighlightingHelper} for adding highlighted HTML to documentation
*/
@Deprecated(forRemoval = true)
public static @NotNull String getStyledSpan(@NotNull TextAttributesKey attributesKey, @Nullable String value, float saturationFactor) {
return appendStyledSpan(new StringBuilder(), attributesKey, value, saturationFactor).toString();
}
/**
* @deprecated Use {@link QuickDocHighlightingHelper} for adding highlighted HTML to documentation
*/
@Deprecated(forRemoval = true)
public static @NotNull String getStyledSpan(@NotNull TextAttributes attributes, @Nullable String value, float saturationFactor) {
return appendStyledSpan(new StringBuilder(), attributes, value, saturationFactor).toString();
}
/**
* @deprecated Use {@link QuickDocCodeHighlightingHelper} for adding code fragments to documentation
* @deprecated Use {@link QuickDocHighlightingHelper} for adding code fragments to documentation
*/
@Deprecated(forRemoval = true)
public static @NotNull String getHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
@@ -108,6 +113,7 @@ public final class HtmlSyntaxInfoUtil {
return appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(buffer, project, language, codeSnippet, true, saturationFactor);
}
@RequiresReadLock
public static @NotNull StringBuilder appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
@NotNull StringBuilder buffer,
@NotNull Project project,

View File

@@ -1,6 +1,9 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.markdown.utils.doc
import com.intellij.lang.Language
import com.intellij.lang.documentation.DocumentationSettings
import com.intellij.lang.documentation.QuickDocHighlightingHelper
import com.intellij.markdown.utils.doc.impl.DocFlavourDescriptor
import com.intellij.markdown.utils.doc.impl.DocTagRenderer
import com.intellij.openapi.diagnostic.ControlFlowException
@@ -9,7 +12,9 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiFile
import com.intellij.ui.ColorUtil
import com.intellij.util.concurrency.annotations.RequiresReadLock
import com.intellij.util.containers.CollectionFactory
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.ui.UIUtil
@@ -20,9 +25,12 @@ import org.jetbrains.annotations.Contract
import org.jetbrains.annotations.Nls
import java.util.regex.Pattern
/**
* [DocMarkdownToHtmlConverter] handles conversion of Markdown text to HTML, which is intended
* to be displayed in Quick Doc popup, or inline in an editor.
*/
object DocMarkdownToHtmlConverter {
private val LOG = Logger.getInstance(DocMarkdownToHtmlConverter::class.java)
private val TAG_START_OR_CLOSE_PATTERN: Pattern = Pattern.compile("(<)/?(\\w+)[> ]")
internal val TAG_PATTERN: Pattern = Pattern.compile("^</?([a-z][a-z-_0-9]*)[^>]*>$", Pattern.CASE_INSENSITIVE)
private val SPLIT_BY_LINE_PATTERN: Pattern = Pattern.compile("\n|\r|\r\n")
@@ -65,10 +73,18 @@ object DocMarkdownToHtmlConverter {
))
}
/**
* Converts provided Markdown text to HTML. The results are intended to be used for Quick Documentation.
* If [defaultLanguage] is provided, it will be used for syntax coloring of inline code and code blocks, if language specifier is missing.
* Block and inline code syntax coloring is being done by [QuickDocHighlightingHelper], which honors [DocumentationSettings].
* Conversion must be run within a Read Action as it might require to create intermediate [PsiFile] to highlight block of code,
* or an inline code.
*/
@Contract(pure = true)
@JvmStatic
@RequiresReadLock
@JvmOverloads
fun convert(markdownText: String, project: Project? = null): String {
fun convert(project: Project, markdownText: String, defaultLanguage: Language? = null): String {
val lines = SPLIT_BY_LINE_PATTERN.split(markdownText)
val processedLines = ArrayList<String>(lines.size)
var isInCode = false
@@ -125,7 +141,7 @@ object DocMarkdownToHtmlConverter {
if (!ContainerUtil.isEmpty(tableFormats)) {
val parts = splitTableCols(processedLine)
if (isTableHeaderSeparator(parts)) continue
processedLine = getProcessedRow(isInTable, parts, tableFormats, project)
processedLine = getProcessedRow(project, defaultLanguage, isInTable, parts, tableFormats)
if (!isInTable) processedLine = "<table style=\"border: 0px;\" cellspacing=\"0\">$processedLine"
isInTable = true
}
@@ -142,7 +158,7 @@ object DocMarkdownToHtmlConverter {
var normalizedMarkdown = StringUtil.join(processedLines, "\n")
if (isInTable) normalizedMarkdown += "</table>" //NON-NLS
var html = performConversion(normalizedMarkdown, project)
var html = performConversion(project, defaultLanguage, normalizedMarkdown)
if (html == null) {
html = replaceProhibitedTags(convertNewLinePlaceholdersToTags(markdownText), ContainerUtil.emptyList())
}
@@ -181,10 +197,11 @@ object DocMarkdownToHtmlConverter {
return parts
}
private fun getProcessedRow(isInTable: Boolean,
private fun getProcessedRow(project: Project,
defaultLanguage: Language?,
isInTable: Boolean,
parts: List<String>,
tableFormats: List<String>?,
project: Project?): String {
tableFormats: List<String>?): String {
val openingTagStart = if (isInTable)
"<td style=\"$border\" "
else
@@ -196,7 +213,7 @@ object DocMarkdownToHtmlConverter {
if (i > 0) {
resultBuilder.append(closingTag).append(openingTagStart).append("align=\"").append(getAlign(i, tableFormats)).append("\">")
}
resultBuilder.append(performConversion(parts[i].trim { it <= ' ' }, project))
resultBuilder.append(performConversion(project, defaultLanguage, parts[i].trim { it <= ' ' }))
}
resultBuilder.append(closingTag).append("</tr>")
return resultBuilder.toString()
@@ -215,9 +232,9 @@ object DocMarkdownToHtmlConverter {
private val embeddedHtmlType = IElementType("ROOT")
private fun performConversion(text: @Nls String, project: Project?): @NlsSafe String? {
private fun performConversion(project: Project, defaultLanguage: Language?, text: @Nls String): @NlsSafe String? {
try {
val flavour = DocFlavourDescriptor(project)
val flavour = DocFlavourDescriptor(project, defaultLanguage)
val parsedTree = MarkdownParser(flavour).parse(embeddedHtmlType, text, true)
return HtmlGenerator(text, parsedTree, flavour, false)
.generateHtml(DocTagRenderer(text))

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.markdown.utils.doc.impl
import com.intellij.lang.Language
import com.intellij.openapi.project.Project
import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownElementTypes
@@ -18,7 +19,7 @@ import org.intellij.markdown.parser.markerblocks.MarkerBlockProvider
import org.intellij.markdown.parser.markerblocks.providers.HtmlBlockProvider
import java.net.URI
internal class DocFlavourDescriptor(private val project: Project?) : GFMFlavourDescriptor() {
internal class DocFlavourDescriptor(private val project: Project, private val defaultLanguage: Language?) : GFMFlavourDescriptor() {
override val markerProcessorFactory: MarkerProcessorFactory
get() = object : MarkerProcessorFactory {
override fun createMarkerProcessor(productionHolder: ProductionHolder): MarkerProcessor<*> =
@@ -28,8 +29,8 @@ internal class DocFlavourDescriptor(private val project: Project?) : GFMFlavourD
override fun createHtmlGeneratingProviders(linkMap: LinkMap, baseURI: URI?): Map<IElementType, GeneratingProvider> {
val result = HashMap(super.createHtmlGeneratingProviders(linkMap, baseURI))
result[MarkdownTokenTypes.HTML_TAG] = DocSanitizingTagGeneratingProvider()
result[MarkdownElementTypes.CODE_FENCE] = DocCodeFenceGeneratingProvider(project)
result[MarkdownElementTypes.CODE_SPAN] = DocCodeSpanGeneratingProvider()
result[MarkdownElementTypes.CODE_FENCE] = DocCodeFenceGeneratingProvider(project, defaultLanguage)
result[MarkdownElementTypes.CODE_SPAN] = DocCodeSpanGeneratingProvider(project, defaultLanguage)
return result
}

View File

@@ -1,8 +1,9 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.markdown.utils.doc.impl
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.guessLanguage
import com.intellij.lang.Language
import com.intellij.lang.documentation.QuickDocHighlightingHelper
import com.intellij.lang.documentation.QuickDocHighlightingHelper.guessLanguage
import com.intellij.markdown.utils.doc.DocMarkdownToHtmlConverter
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
@@ -33,7 +34,7 @@ internal class DocSanitizingTagGeneratingProvider : GeneratingProvider {
}
}
internal class DocCodeFenceGeneratingProvider(private val project: Project?) : GeneratingProvider {
internal class DocCodeFenceGeneratingProvider(private val project: Project, private val defaultLanguage: Language?) : GeneratingProvider {
override fun processNode(visitor: HtmlGenerator.HtmlGeneratingVisitor, text: String, node: ASTNode) {
val contents = StringBuilder()
var language: String? = null
@@ -45,17 +46,18 @@ internal class DocCodeFenceGeneratingProvider(private val project: Project?) : G
language = HtmlGenerator.leafText(text, child).toString().trim().split(' ')[0]
}
}
visitor.consumeHtml(QuickDocCodeHighlightingHelper.getStyledCodeBlock(contents.toString(), guessLanguage(language), project))
visitor.consumeHtml(QuickDocHighlightingHelper.getStyledCodeBlock(
project, guessLanguage(language) ?: defaultLanguage, contents.toString()))
}
}
internal class DocCodeSpanGeneratingProvider : GeneratingProvider {
internal class DocCodeSpanGeneratingProvider(private val project: Project, private val defaultLanguage: Language?) : GeneratingProvider {
override fun processNode(visitor: HtmlGenerator.HtmlGeneratingVisitor, text: String, node: ASTNode) {
val nodes = node.children.subList(1, node.children.size - 1)
val output = nodes
.filter { it.type != MarkdownTokenTypes.BLOCK_QUOTE }
.joinToString(separator = "") { it.getTextInNode(text) }.trim()
visitor.consumeHtml(QuickDocCodeHighlightingHelper.getStyledInlineCode(output))
visitor.consumeHtml(QuickDocHighlightingHelper.getStyledInlineCode(project, defaultLanguage, output))
}
}

View File

@@ -6,12 +6,14 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme
import com.intellij.openapi.editor.impl.EditorCssFontResolver
import com.intellij.ui.ColorUtil
import com.intellij.util.containers.addAllIfNotNull
import org.jetbrains.annotations.ApiStatus.Internal
import java.awt.Color
import kotlin.math.abs
/**
* Provides list of CSS rules for rendering code tags
*/
@Internal
object StyleSheetRulesProviderForCodeHighlighting {
const val CODE_BLOCK_PREFIX = "<div class='styled-code'><pre style=\"padding: 0px; margin: 0px\">"

View File

@@ -64,7 +64,7 @@ abstract class CustomElementsManifestScopeBase :
protected class CustomElementsManifestJsonOriginImpl(
override val library: String,
private val project: Project?,
private val project: Project,
override val version: String? = null,
override val typeSupport: WebSymbolTypeSupport? = null,
private val sourceSymbolResolver: (source: SourceReference, cacheHolder: UserDataHolderEx) -> PsiElement? = { _, _ -> null },
@@ -76,7 +76,7 @@ abstract class CustomElementsManifestScopeBase :
sourceSymbolResolver(source, cacheHolder)
override fun renderDescription(description: String): String =
DocMarkdownToHtmlConverter.convert(description, project)
DocMarkdownToHtmlConverter.convert(project, description)
override fun toString(): String {
return "$library@$version"

View File

@@ -2,11 +2,13 @@
package com.intellij.webSymbols.utils;
import com.intellij.markdown.utils.doc.DocMarkdownToHtmlConverter;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
/**
* @deprecated Use {@link DocMarkdownToHtmlConverter} directly
* @deprecated Use {@link DocMarkdownToHtmlConverter#convert(Project, String)} instead
*/
@Deprecated(forRemoval = true)
public final class HtmlMarkdownUtils {
@@ -16,13 +18,13 @@ public final class HtmlMarkdownUtils {
@Contract(pure = true)
public static @NotNull String toHtml(@NotNull String markdownText) {
return DocMarkdownToHtmlConverter.convert(markdownText);
return DocMarkdownToHtmlConverter.convert(DefaultProjectFactory.getInstance().getDefaultProject(), markdownText);
}
@Contract(pure = true)
public static @NotNull String toHtml(@NotNull String markdownText, boolean convertTagCodeBlocks) {
return DocMarkdownToHtmlConverter.convert(markdownText);
return DocMarkdownToHtmlConverter.convert(DefaultProjectFactory.getInstance().getDefaultProject(), markdownText);
}
}

View File

@@ -184,7 +184,7 @@ abstract class WebTypesScopeBase :
protected class WebTypesJsonOriginImpl(
webTypes: WebTypes,
override val typeSupport: WebSymbolTypeSupport,
private val project: Project?,
private val project: Project,
private val symbolLocationResolver: (source: SourceBase) -> WebTypesSymbol.Location? = { null },
private val sourceSymbolResolver: (location: WebTypesSymbol.Location, cacheHolder: UserDataHolderEx) -> PsiElement? = { _, _ -> null },
private val iconLoader: (path: String) -> Icon? = { null },
@@ -198,7 +198,7 @@ abstract class WebTypesScopeBase :
private val descriptionRenderer: (String) -> String =
when (webTypes.descriptionMarkupWithLegacy) {
WebTypes.DescriptionMarkup.HTML -> { doc -> doc }
WebTypes.DescriptionMarkup.MARKDOWN -> { doc -> DocMarkdownToHtmlConverter.convert(doc, project) }
WebTypes.DescriptionMarkup.MARKDOWN -> { doc -> DocMarkdownToHtmlConverter.convert(project, doc) }
else -> { doc -> "<p>" + StringUtil.escapeXmlEntities(doc).replace(EOL_PATTERN, "<br>") }
}

View File

@@ -12,10 +12,10 @@ import com.intellij.testFramework.UsefulTestCase
import com.intellij.webSymbols.context.WebSymbolsContext.Companion.KIND_FRAMEWORK
import com.intellij.webSymbols.context.impl.WebSymbolsContextProviderExtensionPoint
import com.intellij.webSymbols.query.impl.CustomElementsManifestMockScopeImpl
import com.intellij.webSymbols.webTypes.filters.WebSymbolsMatchPrefixFilter
import com.intellij.webSymbols.webTypes.impl.WebSymbolsFilterEP
import com.intellij.webSymbols.query.impl.WebSymbolsMockQueryExecutorFactory
import com.intellij.webSymbols.query.impl.WebTypesMockScopeImpl
import com.intellij.webSymbols.webTypes.filters.WebSymbolsMatchPrefixFilter
import com.intellij.webSymbols.webTypes.impl.WebSymbolsFilterEP
import java.io.File
abstract class WebSymbolsMockQueryExecutorTestBase : UsefulTestCase() {
@@ -63,7 +63,7 @@ abstract class WebSymbolsMockQueryExecutorTestBase : UsefulTestCase() {
fun registerFiles(framework: String?, webTypes: List<String>, customElementManifests: List<String>) {
framework?.let { (webSymbolsQueryExecutorFactory as WebSymbolsMockQueryExecutorFactory).context[KIND_FRAMEWORK] = it }
if (webTypes.isNotEmpty()) {
webSymbolsQueryExecutorFactory.addScope(WebTypesMockScopeImpl().also { scope ->
webSymbolsQueryExecutorFactory.addScope(WebTypesMockScopeImpl(testRootDisposable).also { scope ->
webTypes.forEach { file ->
scope.registerFile(File(testPath, "../$file.web-types.json").takeIf { it.exists() }
?: File(testPath, "../../common/$file.web-types.json"))
@@ -71,7 +71,7 @@ abstract class WebSymbolsMockQueryExecutorTestBase : UsefulTestCase() {
}, null, testRootDisposable)
}
if (customElementManifests.isNotEmpty()) {
webSymbolsQueryExecutorFactory.addScope(CustomElementsManifestMockScopeImpl().also {scope ->
webSymbolsQueryExecutorFactory.addScope(CustomElementsManifestMockScopeImpl(testRootDisposable).also { scope ->
customElementManifests.forEach { file ->
scope.registerFile(File(testPath, "../$file.custom-elements-manifest.json").takeIf { it.exists() }
?: File(testPath, "../../common/$file.custom-elements-manifest.json"))

View File

@@ -1,18 +1,20 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.webSymbols.query.impl
import com.intellij.mock.MockProjectEx
import com.intellij.model.Pointer
import com.intellij.openapi.Disposable
import com.intellij.webSymbols.customElements.CustomElementsManifestScopeBase
import com.intellij.webSymbols.customElements.readCustomElementsManifest
import java.io.File
internal class CustomElementsManifestMockScopeImpl : CustomElementsManifestScopeBase() {
internal class CustomElementsManifestMockScopeImpl(private val disposable: Disposable) : CustomElementsManifestScopeBase() {
fun registerFile(file: File) {
val manifest = readCustomElementsManifest(file.toString())
val context = CustomElementsManifestJsonOriginImpl(
file.name.takeWhile { it != '.' },
project = null,
project = MockProjectEx(disposable),
typeSupport = WebSymbolsMockTypeSupport
)
addCustomElementsManifest(manifest, context)

View File

@@ -1,19 +1,21 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.webSymbols.query.impl
import com.intellij.mock.MockProjectEx
import com.intellij.model.Pointer
import com.intellij.openapi.Disposable
import com.intellij.webSymbols.webTypes.WebTypesJsonFilesCache
import com.intellij.webSymbols.webTypes.WebTypesScopeBase
import java.io.File
internal class WebTypesMockScopeImpl : WebTypesScopeBase() {
internal class WebTypesMockScopeImpl(private val disposable: Disposable) : WebTypesScopeBase() {
fun registerFile(file: File) {
val webTypes = WebTypesJsonFilesCache.fromUrlNoCache(file.toURI().toString())
val context = WebTypesJsonOriginImpl(
webTypes,
typeSupport = WebSymbolsMockTypeSupport,
project = null
project = MockProjectEx(disposable),
)
addWebTypes(webTypes, context)
}

View File

@@ -3,9 +3,8 @@ package org.jetbrains.plugins.groovy.lang.documentation;
import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory;
import com.intellij.ide.highlighter.JavaHighlightingColors;
import com.intellij.lang.documentation.DocumentationSettings;
import com.intellij.lang.documentation.QuickDocHighlightingHelper;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiElement;
@@ -137,7 +136,7 @@ public final class GroovyPresentationUtil {
@Nullable String value
) {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(buffer, attributesKey, value, DocumentationSettings.getHighlightingSaturation(false));
QuickDocHighlightingHelper.appendStyledFragment(buffer, value, attributesKey);
}
else {
buffer.append(value);

View File

@@ -61,7 +61,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import static com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledSignatureFragment;
import static com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledSignatureFragment;
public class GroovyDocumentationProvider implements CodeDocumentationProvider, ExternalDocumentationProvider {

View File

@@ -6,11 +6,12 @@ import com.intellij.codeInsight.documentation.DocumentationManagerUtil
import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory
import com.intellij.lang.documentation.DocumentationMarkup.*
import com.intellij.lang.documentation.DocumentationSettings
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledCodeBlock
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledInlineCode
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledInlineCodeFragment
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper.appendStyledLinkFragment
import com.intellij.lang.documentation.QuickDocHighlightingHelper
import com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledCodeBlock
import com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledFragment
import com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledInlineCode
import com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledInlineCodeFragment
import com.intellij.lang.documentation.QuickDocHighlightingHelper.appendStyledLinkFragment
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.openapi.editor.HighlighterColors
@@ -18,7 +19,6 @@ import com.intellij.openapi.editor.colors.CodeInsightColors
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
@@ -200,14 +200,14 @@ object KDocRenderer {
append("<p>")
this@appendSamplesList.appendHyperlink(subjectLink)
this@appendSamplesList.appendStyledCodeBlock(
subjectLink.project,
KotlinLanguage.INSTANCE,
if (DumbService.isDumb(subjectLink.project))
"// " + KotlinBundle.message("kdoc.comment.unresolved")
else when (val target = subjectLink.getTargetElement()) {
null -> "// " + KotlinBundle.message("kdoc.comment.unresolved")
else -> trimCommonIndent(target.extractExampleText()).htmlEscape()
},
KotlinLanguage.INSTANCE,
subjectLink.project
}
)
}
}
@@ -388,7 +388,7 @@ object KDocRenderer {
val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text
if (startDelimiter != null) {
val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter)
sb.appendStyledInlineCode(text, KotlinLanguage.INSTANCE, comment.project)
sb.appendStyledInlineCode(comment.project, KotlinLanguage.INSTANCE, text)
}
}
@@ -406,7 +406,11 @@ object KDocRenderer {
language = child.text.trim().split(' ')[0]
}
}
sb.appendStyledCodeBlock(contents, QuickDocCodeHighlightingHelper.guessLanguage(language) ?: KotlinLanguage.INSTANCE)
sb.appendStyledCodeBlock(
project = comment.project,
language = QuickDocHighlightingHelper.guessLanguage(language) ?: KotlinLanguage.INSTANCE,
code = contents
)
}
MarkdownTokenTypes.FENCE_LANG, MarkdownTokenTypes.CODE_LINE, MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
@@ -438,7 +442,7 @@ object KDocRenderer {
true
)
}
?: sb.appendStyledSpan(true, KotlinHighlightingColors.RESOLVED_TO_ERROR, label)
?: sb.appendStyledFragment(label, KotlinHighlightingColors.RESOLVED_TO_ERROR)
}
} else {
sb.append(node.text)
@@ -566,15 +570,6 @@ object KDocRenderer {
}
}
private fun StringBuilder.appendStyledSpan(doHighlighting: Boolean, attributesKey: TextAttributesKey, value: String?): StringBuilder {
if (doHighlighting) {
HtmlSyntaxInfoUtil.appendStyledSpan(this, attributesKey, value, DocumentationSettings.getHighlightingSaturation(true))
} else {
append(value)
}
return this
}
/**
* If highlighted links has the same color as highlighted inline code blocks they will be indistinguishable.
* In this case we should change link color to standard hyperlink color which we believe is apriori different.
@@ -633,16 +628,11 @@ object KDocRenderer {
value: String,
attributes: TextAttributesAdapter
) {
HtmlSyntaxInfoUtil.appendStyledSpan(
this,
attributes.attributes,
value,
DocumentationSettings.getHighlightingSaturation(false)
)
appendStyledFragment(value, attributes.attributes)
}
override fun StringBuilder.appendCodeSnippetHighlightedByLexer(codeSnippet: String) {
appendStyledInlineCodeFragment(codeSnippet, KotlinLanguage.INSTANCE, project)
appendStyledInlineCodeFragment(project, KotlinLanguage.INSTANCE, codeSnippet)
}
private fun resolveKey(key: TextAttributesKey): TextAttributesAdapter {

View File

@@ -1,20 +1,18 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python
import com.intellij.lang.documentation.DocumentationSettings
import com.intellij.lang.documentation.QuickDocCodeHighlightingHelper
import com.intellij.lang.documentation.QuickDocHighlightingHelper
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil
import com.intellij.openapi.project.Project
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
class PythonDocumentationHighlightingServiceImpl : PythonDocumentationHighlightingService() {
override fun highlightedCodeSnippet(project: Project, codeSnippet: String): String {
return QuickDocCodeHighlightingHelper.getStyledInlineCodeFragment(codeSnippet, PythonLanguage.INSTANCE, project)
return QuickDocHighlightingHelper.getStyledInlineCodeFragment(project, PythonLanguage.INSTANCE, codeSnippet)
}
override fun styledSpan(textAttributeKey: TextAttributesKey, text: String): String {
return HtmlSyntaxInfoUtil.getStyledSpan(textAttributeKey, text, DocumentationSettings.getHighlightingSaturation(false))
return QuickDocHighlightingHelper.getStyledFragment(text, textAttributeKey)
}
}

View File

@@ -15,6 +15,7 @@ import com.github.benmanes.caffeine.cache.Caffeine
import com.github.benmanes.caffeine.cache.LoadingCache
import com.intellij.lang.documentation.DocumentationMarkup
import com.intellij.markdown.utils.doc.DocMarkdownToHtmlConverter
import com.intellij.openapi.project.DefaultProjectFactory
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.util.text.StringUtil.capitalize
import com.intellij.openapi.util.text.StringUtil.toLowerCase
@@ -209,7 +210,12 @@ class MdnSymbolDocumentationAdapter(override val name: String,
override val description: String
get() = capitalize(
doc.doc?.let { if (it.contains("```")) DocMarkdownToHtmlConverter.convert(it) else it } ?: ""
doc.doc?.let {
if (it.contains("```"))
DocMarkdownToHtmlConverter.convert(DefaultProjectFactory.getInstance().defaultProject, it)
else
it
} ?: ""
).fixUrls()
override val sections: Map<String, String>