mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-65956 QuickDoc: ensure that <td> has a nested <p> or other block element.
GitOrigin-RevId: 88e43669da966071c3109972849d72fdf00c67ce
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5f519ec45c
commit
edef8d4a82
+1
-1
@@ -5,4 +5,4 @@
|
||||
at least one element <tt>e</tt> such that
|
||||
<tt>(o==null ? e==null : o.<wbr>equals(e))</tt>.
|
||||
|
||||
</p></div><table class="sections"><tbody><tr><td valign="top" class="section"><p>Overrides:</p></td><td valign="top"><p><a href="psi_element://java.util.Collection#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://java.util.Collection"><code><span style="color:#000000;">Collection</span></code></a></p></td></tr><tr><td valign="top" class="section"><p>Params:</p></td><td valign="top"><code><span style="color:#000000;">o</span></code> – element whose presence in this list is to be tested </td></tr><tr><td valign="top" class="section"><p>Returns:</p></td><td valign="top"><p><tt>true</tt> if this list contains the specified element </p></td></tr><tr><td valign="top" class="section"><p>Throws:</p></td><td valign="top"><p><a href="psi_element://java.lang.ClassCastException"><code><span style="color:#0000ff;">ClassCastException</span></code></a> – if the type of the specified element is incompatible with this list (<a href="psi_element://java.util.Collection###optional-restrictions">optional</a>) </p><p><a href="psi_element://java.lang.NullPointerException"><code><span style="color:#0000ff;">NullPointerException</span></code></a> – if the specified element is null and this list does not permit null elements (<a href="psi_element://java.util.Collection###optional-restrictions">optional</a>)</p></td></tr></tbody></table><div class="bottom"><icon src="AllIcons.Nodes.PpLibFolder" /> < java 1.7 ></div></body></html>
|
||||
</p></div><table class="sections"><tbody><tr><td valign="top" class="section"><p>Overrides:</p></td><td valign="top"><p><a href="psi_element://java.util.Collection#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://java.util.Collection"><code><span style="color:#000000;">Collection</span></code></a></p></td></tr><tr><td valign="top" class="section"><p>Params:</p></td><td valign="top"><p><code><span style="color:#000000;">o</span></code> – element whose presence in this list is to be tested </p></td></tr><tr><td valign="top" class="section"><p>Returns:</p></td><td valign="top"><p><tt>true</tt> if this list contains the specified element </p></td></tr><tr><td valign="top" class="section"><p>Throws:</p></td><td valign="top"><p><a href="psi_element://java.lang.ClassCastException"><code><span style="color:#0000ff;">ClassCastException</span></code></a> – if the type of the specified element is incompatible with this list (<a href="psi_element://java.util.Collection###optional-restrictions">optional</a>) </p><p><a href="psi_element://java.lang.NullPointerException"><code><span style="color:#0000ff;">NullPointerException</span></code></a> – if the specified element is null and this list does not permit null elements (<a href="psi_element://java.util.Collection###optional-restrictions">optional</a>)</p></td></tr></tbody></table><div class="bottom"><icon src="AllIcons.Nodes.PpLibFolder" /> < java 1.7 ></div></body></html>
|
||||
+1
-1
@@ -6,4 +6,4 @@
|
||||
contains at least one element <tt>e</tt> such that
|
||||
<tt>(o==null ? e==null : o.<wbr>equals(e))</tt>.
|
||||
|
||||
</p></td></tr><tr><td valign="top" class="section"><p>Overrides:</p></td><td valign="top"><p><a href="psi_element://java.util.Collection#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://java.util.Collection"><code><span style="color:#000000;">Collection</span></code></a><br><a href="psi_element://I#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://I"><code><span style="color:#000000;">I</span></code></a></p></td></tr><tr><td valign="top" class="section"><p>Params:</p></td><td valign="top"><code><span style="color:#000000;">o</span></code> – element whose presence in this collection is to be tested </td></tr><tr><td valign="top" class="section"><p>Returns:</p></td><td valign="top"><p><tt>true</tt> if this collection contains the specified element </p></td></tr><tr><td valign="top" class="section"><p>Throws:</p></td><td valign="top"><p><a href="psi_element://java.lang.NullPointerException"><code><span style="color:#0000ff;">NullPointerException</span></code></a> – before if the specified element is null and this collection does not permit null elements (<a href="psi_element://My###optional-restrictions">optional</a>) after</p><p><span style="color:#ff0000">IOException</span></p></td></tr></tbody></table></body></html>
|
||||
</p></td></tr><tr><td valign="top" class="section"><p>Overrides:</p></td><td valign="top"><p><a href="psi_element://java.util.Collection#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://java.util.Collection"><code><span style="color:#000000;">Collection</span></code></a><br><a href="psi_element://I#contains(java.lang.Object)"><code><span style="color:#000000;">contains</span></code></a> in interface <a href="psi_element://I"><code><span style="color:#000000;">I</span></code></a></p></td></tr><tr><td valign="top" class="section"><p>Params:</p></td><td valign="top"><p><code><span style="color:#000000;">o</span></code> – element whose presence in this collection is to be tested </p></td></tr><tr><td valign="top" class="section"><p>Returns:</p></td><td valign="top"><p><tt>true</tt> if this collection contains the specified element </p></td></tr><tr><td valign="top" class="section"><p>Throws:</p></td><td valign="top"><p><a href="psi_element://java.lang.NullPointerException"><code><span style="color:#0000ff;">NullPointerException</span></code></a> – before if the specified element is null and this collection does not permit null elements (<a href="psi_element://My###optional-restrictions">optional</a>) after</p><p><span style="color:#ff0000">IOException</span></p></td></tr></tbody></table></body></html>
|
||||
+2
-2
@@ -109,8 +109,8 @@ public class JavaDocRenderTest extends AbstractEditorTest {
|
||||
* @author bar
|
||||
*/
|
||||
class C {}""", true);
|
||||
verifyItem(15, 52,"<table class='sections'><p><tr><td valign='top' class='section'><p>Author:</td>" +
|
||||
"<td valign='top'><p>foo, bar</td></table>");
|
||||
verifyItem(15, 52,"<table class=\"sections\"><tbody><tr><td valign=\"top\" class=\"section\"><p>Author:</p></td>" +
|
||||
"<td valign=\"top\"><p>foo, bar</p></td></tr></tbody></table>");
|
||||
}
|
||||
|
||||
public void testDocumentStart() {
|
||||
|
||||
+48
@@ -7,11 +7,14 @@ import com.intellij.openapi.module.UnknownModuleType
|
||||
import com.intellij.ui.ColorUtil
|
||||
import com.intellij.ui.components.JBHtmlPaneStyleConfiguration
|
||||
import com.intellij.ui.scale.JBUIScale.scale
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.StyleSheetUtil
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jsoup.nodes.*
|
||||
import java.util.*
|
||||
import java.util.function.Function
|
||||
import javax.swing.Icon
|
||||
import javax.swing.text.html.StyleSheet
|
||||
@@ -98,4 +101,49 @@ object DocumentationHtmlUtil {
|
||||
""".trimIndent()
|
||||
return StyleSheetUtil.loadStyleSheet(result)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
internal fun addExternalLinkIcons(document: Document) {
|
||||
document.select("a").forEach { a ->
|
||||
if (a.attribute("href")?.value?.startsWith("http") == true) {
|
||||
Element("icon").attr("src", "AllIcons.Ide.External_link_arrow")
|
||||
.appendTo(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
internal fun addParagraphsIfNeeded(document: Document, selector: String) {
|
||||
document.select(selector).forEach { element ->
|
||||
var child = element.firstChild()
|
||||
val toWrap = SmartList<Node>()
|
||||
while (child != null && !isBlockElement(child)) {
|
||||
if (child !is Comment) {
|
||||
toWrap.add(child);
|
||||
}
|
||||
child = child.nextSibling();
|
||||
}
|
||||
if (!toWrap.isEmpty() && !toWrap.all { n -> n is TextNode && n.isBlank }) {
|
||||
val para = Element("p");
|
||||
para.insertChildren(0, toWrap);
|
||||
element.insertChildren(0, para);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isBlockElement(node: Node): Boolean {
|
||||
if (node is Element) {
|
||||
val tagName = node.tagName().lowercase(Locale.US)
|
||||
return tagName == "p"
|
||||
|| tagName == "div"
|
||||
|| tagName == "pre"
|
||||
|| tagName == "table"
|
||||
|| tagName == "blockquote"
|
||||
|| tagName == "ol"
|
||||
|| tagName == "ul"
|
||||
|| tagName == "dl"
|
||||
|| (tagName.startsWith("h") && tagName.length == 2 && Character.isDigit(tagName[1]))
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
+6
-50
@@ -84,10 +84,7 @@ import org.jetbrains.annotations.*;
|
||||
import org.jetbrains.concurrency.CancellablePromise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Comment;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Node;
|
||||
import org.jsoup.nodes.TextNode;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -107,7 +104,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.intellij.lang.documentation.DocumentationMarkup.*;
|
||||
|
||||
@@ -1948,14 +1944,14 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
document.body().append(getBottom().child(links).toString());
|
||||
}
|
||||
|
||||
document.select("." + CLASS_DEFINITION + ", ." + CLASS_CONTENT).forEach(
|
||||
document.select("." + CLASS_DEFINITION + ", ." + CLASS_CONTENT + ", ." + CLASS_SECTIONS).forEach(
|
||||
div -> {
|
||||
var nextSibling = div.nextElementSibling();
|
||||
if (nextSibling == null) {
|
||||
return;
|
||||
}
|
||||
if (nextSibling.hasClass(CLASS_DEFINITION)
|
||||
|| nextSibling.hasClass(CLASS_CONTENT)
|
||||
|| (nextSibling.hasClass(CLASS_CONTENT) && !div.hasClass(CLASS_SECTIONS))
|
||||
|| (div.hasClass(CLASS_DEFINITION)
|
||||
&& (
|
||||
nextSibling.hasClass(CLASS_SECTIONS)
|
||||
@@ -1966,44 +1962,11 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
}
|
||||
);
|
||||
document.select("." + CLASS_CONTENT).forEach(
|
||||
div -> {
|
||||
var child = div.firstChild();
|
||||
var toWrap = new SmartList<Node>();
|
||||
while (child != null && !isBlockElement(child)) {
|
||||
if (!(child instanceof Comment)) {
|
||||
toWrap.add(child);
|
||||
}
|
||||
child = child.nextSibling();
|
||||
}
|
||||
if (!toWrap.isEmpty()
|
||||
&& !ContainerUtil.all(toWrap, n -> n instanceof TextNode textNode && textNode.isBlank())
|
||||
) {
|
||||
var para = new Element("p");
|
||||
para.insertChildren(0, toWrap);
|
||||
div.insertChildren(0, para);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
DocumentationHtmlUtil.addParagraphsIfNeeded$intellij_platform_lang_impl(
|
||||
document, "." + CLASS_CONTENT + ", table." + CLASS_SECTIONS + " td[valign=top]");
|
||||
DocumentationHtmlUtil.addExternalLinkIcons$intellij_platform_lang_impl(document);
|
||||
document.outputSettings().prettyPrint(false);
|
||||
return addExternalLinksIcon(document.html());
|
||||
}
|
||||
|
||||
private static boolean isBlockElement(Node node) {
|
||||
if (node instanceof Element element) {
|
||||
var tagName = element.tagName();
|
||||
return tagName.equals("p")
|
||||
|| tagName.equals("div")
|
||||
|| tagName.equals("pre")
|
||||
|| tagName.equals("table")
|
||||
|| tagName.equals("blockquote")
|
||||
|| tagName.equals("ol")
|
||||
|| tagName.equals("ul")
|
||||
|| tagName.equals("dl")
|
||||
|| (tagName.startsWith("h") && tagName.length() == 2 && Character.isDigit(tagName.charAt(1)));
|
||||
}
|
||||
return false;
|
||||
return document.html();
|
||||
}
|
||||
|
||||
private static @NlsSafe @NotNull String replaceIgnoreQuotesType(@NotNull String text,
|
||||
@@ -2136,11 +2099,4 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return HtmlChunk.div().setClass(CLASS_BOTTOM);
|
||||
}
|
||||
|
||||
private static final Pattern EXTERNAL_LINK_PATTERN = Pattern.compile("(<a\\s*href=[\"']http[^>]*>)([^>]*)(</a>)");
|
||||
private static final @NlsSafe String EXTERNAL_LINK_REPLACEMENT = "$1$2<icon src='AllIcons.Ide.External_link_arrow'>$3";
|
||||
|
||||
@Contract(pure = true)
|
||||
public static String addExternalLinksIcon(String text) {
|
||||
return EXTERNAL_LINK_PATTERN.matcher(text).replaceAll(EXTERNAL_LINK_REPLACEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -3,7 +3,7 @@ package com.intellij.codeInsight.documentation.render;
|
||||
|
||||
import com.intellij.codeHighlighting.*;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager;
|
||||
import com.intellij.codeInsight.documentation.DocumentationHtmlUtil;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -20,12 +20,14 @@ import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.intellij.codeInsight.documentation.render.InlineDocumentationImplKt.inlineDocumentationItems;
|
||||
import static com.intellij.lang.documentation.DocumentationMarkup.CLASS_SECTIONS;
|
||||
|
||||
public final class DocRenderPassFactory implements TextEditorHighlightingPassFactoryRegistrar, TextEditorHighlightingPassFactory, DumbAware {
|
||||
private static final Key<Long> MODIFICATION_STAMP = Key.create("doc.render.modification.stamp");
|
||||
@@ -113,7 +115,12 @@ public final class DocRenderPassFactory implements TextEditorHighlightingPassFac
|
||||
}
|
||||
|
||||
private static String preProcess(String text) {
|
||||
return DocumentationManager.addExternalLinksIcon(text);
|
||||
var document = Jsoup.parse(text);
|
||||
DocumentationHtmlUtil.addParagraphsIfNeeded$intellij_platform_lang_impl(
|
||||
document, "table." + CLASS_SECTIONS + " td[valign=top]");
|
||||
DocumentationHtmlUtil.addExternalLinkIcons$intellij_platform_lang_impl(document);
|
||||
document.outputSettings().prettyPrint(false);
|
||||
return document.html();
|
||||
}
|
||||
|
||||
public static void applyItemsToRender(@NotNull Editor editor,
|
||||
|
||||
Reference in New Issue
Block a user