mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
[util] IJPL-208889 MarkupText experimental API
A simple model of a text line with markup which doesn't depend on Swing to be used in completion, etc. GitOrigin-RevId: 3aef202aa8f00edf149f11f6d3b859456ba44fe0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
228f01a833
commit
ea5fa1b63f
@@ -0,0 +1,5 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@Internal
|
||||
package com.intellij.modcompletion;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||
@@ -13,5 +13,7 @@
|
||||
- getToolTip(Z):java.lang.String
|
||||
- hashCode():I
|
||||
- paintIcon(java.awt.Component,java.awt.Graphics,I,I):V
|
||||
f:com.intellij.ui.SimpleTextAttributes
|
||||
- *s:fromMarkupTextKind(com.intellij.openapi.util.text.MarkupText$Kind):com.intellij.ui.SimpleTextAttributes
|
||||
f:com.intellij.util.IconUtil
|
||||
- *sf:downscaleIconToSize(javax.swing.Icon,I,I):javax.swing.Icon
|
||||
|
||||
@@ -4,11 +4,13 @@ package com.intellij.ui;
|
||||
import com.intellij.openapi.editor.markup.EffectType;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.MarkupText;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.NamedColorUtil;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -203,6 +205,25 @@ public final class SimpleTextAttributes {
|
||||
return BitUtil.isSet(myStyle, STYLE_FADED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts {@link MarkupText.Kind} to {@code SimpleTextAttributes}.
|
||||
*
|
||||
* @param kind kind of {@link MarkupText}
|
||||
* @return the corresponding {@code SimpleTextAttributes} object
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public static @NotNull SimpleTextAttributes fromMarkupTextKind(MarkupText.@NotNull Kind kind) {
|
||||
return switch (kind) {
|
||||
case NORMAL -> REGULAR_ATTRIBUTES;
|
||||
case EMPHASIZED -> REGULAR_ITALIC_ATTRIBUTES;
|
||||
case STRONG -> REGULAR_BOLD_ATTRIBUTES;
|
||||
case UNDERLINED -> new SimpleTextAttributes(STYLE_UNDERLINE, null);
|
||||
case ERROR -> ERROR_ATTRIBUTES;
|
||||
case STRIKEOUT -> new SimpleTextAttributes(STYLE_STRIKEOUT, null);
|
||||
case GRAYED -> GRAYED_ATTRIBUTES;
|
||||
};
|
||||
}
|
||||
|
||||
public static @NotNull SimpleTextAttributes fromTextAttributes(TextAttributes attributes) {
|
||||
if (attributes == null) return REGULAR_ATTRIBUTES;
|
||||
|
||||
|
||||
@@ -375,6 +375,7 @@ c:com.intellij.ui.SimpleColoredComponent
|
||||
- javax.swing.JComponent
|
||||
- com.intellij.ui.ColoredTextContainer
|
||||
- javax.accessibility.Accessible
|
||||
- *s:fromMarkupText(com.intellij.openapi.util.text.MarkupText):com.intellij.ui.SimpleColoredComponent
|
||||
- *p:getIconToolTipText():java.lang.String
|
||||
*c:com.intellij.ui.components.JBHtmlPane
|
||||
- com.intellij.openapi.Disposable
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.ui.GraphicsConfig;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.MarkupText;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.icons.IconWithToolTip;
|
||||
import com.intellij.ui.paint.EffectPainter;
|
||||
@@ -284,6 +285,20 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co
|
||||
revalidateAndRepaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code SimpleColoredComponent} from {@link MarkupText}.
|
||||
* @param text markup text
|
||||
* @return a newly created {@code SimpleColoredComponent} that visualizes the specified text
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public static SimpleColoredComponent fromMarkupText(@NotNull MarkupText text) {
|
||||
SimpleColoredComponent component = new SimpleColoredComponent();
|
||||
for (MarkupText.Fragment fragment : text.fragments()) {
|
||||
component.append(fragment.text(), SimpleTextAttributes.fromMarkupTextKind(fragment.kind()));
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
private void _clear() {
|
||||
synchronized (myFragments) {
|
||||
myIcon = null;
|
||||
|
||||
@@ -65,6 +65,43 @@ f:com.intellij.openapi.util.text.HtmlChunkUtilKt
|
||||
- *sf:buildHtml(kotlin.jvm.functions.Function1):java.lang.String
|
||||
- *sf:buildHtmlChunk(kotlin.jvm.functions.Function1):com.intellij.openapi.util.text.HtmlChunk
|
||||
- *sf:plus(com.intellij.openapi.util.text.HtmlChunk,com.intellij.openapi.util.text.HtmlChunk):com.intellij.openapi.util.text.HtmlChunk
|
||||
*f:com.intellij.openapi.util.text.MarkupText
|
||||
- s:builder():com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- concat(com.intellij.openapi.util.text.MarkupText):com.intellij.openapi.util.text.MarkupText
|
||||
- concat(java.lang.String,com.intellij.openapi.util.text.MarkupText$Kind):com.intellij.openapi.util.text.MarkupText
|
||||
- equals(java.lang.Object):Z
|
||||
- fragments():java.util.List
|
||||
- hashCode():I
|
||||
- highlightRange(I,I,com.intellij.openapi.util.text.MarkupText$Kind):com.intellij.openapi.util.text.MarkupText
|
||||
- isEmpty():Z
|
||||
- length():I
|
||||
- s:plainText(java.lang.String):com.intellij.openapi.util.text.MarkupText
|
||||
- toHtmlChunk():com.intellij.openapi.util.text.HtmlChunk
|
||||
- toText():java.lang.String
|
||||
*f:com.intellij.openapi.util.text.MarkupText$Fragment
|
||||
- <init>(java.lang.String,com.intellij.openapi.util.text.MarkupText$Kind):V
|
||||
- equals(java.lang.Object):Z
|
||||
- hashCode():I
|
||||
- kind():com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- text():java.lang.String
|
||||
- toHtmlChunk():com.intellij.openapi.util.text.HtmlChunk
|
||||
*e:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- java.lang.Enum
|
||||
- sf:EMPHASIZED:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:ERROR:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:GRAYED:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:NORMAL:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:STRIKEOUT:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:STRONG:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- sf:UNDERLINED:com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- s:valueOf(java.lang.String):com.intellij.openapi.util.text.MarkupText$Kind
|
||||
- s:values():com.intellij.openapi.util.text.MarkupText$Kind[]
|
||||
*f:com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- append(com.intellij.openapi.util.text.MarkupText$Fragment):com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- append(com.intellij.openapi.util.text.MarkupText):com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- append(java.lang.String):com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- append(java.lang.String,com.intellij.openapi.util.text.MarkupText$Kind):com.intellij.openapi.util.text.MarkupText$MarkupTextBuilder
|
||||
- build():com.intellij.openapi.util.text.MarkupText
|
||||
com.intellij.ui.IconManager
|
||||
- *:colorizedIcon(javax.swing.Icon,kotlin.jvm.functions.Function0):javax.swing.Icon
|
||||
*f:com.intellij.util.JavaCoroutines
|
||||
|
||||
381
platform/util/src/com/intellij/openapi/util/text/MarkupText.java
Normal file
381
platform/util/src/com/intellij/openapi/util/text/MarkupText.java
Normal file
@@ -0,0 +1,381 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.util.text;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNullByDefault;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents an immutable text string with markup to display in the UI. It's used to display simple one-line text,
|
||||
* like a completion item or a menu item. It's not intended to provide any complex markup like text positioning, indentation, margins, etc.
|
||||
* Only semantic visual markup is supported.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
@NotNullByDefault
|
||||
public final class MarkupText {
|
||||
private static final MarkupText EMPTY = new MarkupText(Collections.emptyList());
|
||||
|
||||
private final List<Fragment> fragments;
|
||||
|
||||
/**
|
||||
* @param fragments list of fragments. They should be displayed one after another.
|
||||
*/
|
||||
private MarkupText(List<Fragment> fragments) { this.fragments = fragments; }
|
||||
|
||||
/**
|
||||
* @return list of fragments.
|
||||
*/
|
||||
public List<Fragment> fragments() { return fragments; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
MarkupText that = (MarkupText)obj;
|
||||
return Objects.equals(this.fragments, that.fragments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fragments.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return textual representation for debug purposes only. It somehow mimics Markdown, but it's not a real Markdown.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringUtil.join(fragments, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HTML representation of the MarkupText. It's assumed that a few CSS classes are defined; namely "grayed" and "error".
|
||||
*/
|
||||
public HtmlChunk toHtmlChunk() {
|
||||
HtmlBuilder builder = new HtmlBuilder();
|
||||
fragments.forEach(fragment -> builder.append(fragment.toHtmlChunk()));
|
||||
return builder.toFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return text of the MarkupText with all the markup stripped out.
|
||||
*/
|
||||
public @Nls String toText() {
|
||||
return StringUtil.join(fragments, Fragment::text, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this MarkupText is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return fragments.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return total length of the MarkupText in characters.
|
||||
*/
|
||||
public int length() {
|
||||
return fragments.stream().mapToInt(f -> f.text.length()).sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates two MarkupTexts.
|
||||
* @param other MarkupText to be concatenated with this one
|
||||
* @return a MarkupText that contains all the fragments of both MarkupTexts.
|
||||
*/
|
||||
public MarkupText concat(MarkupText other) {
|
||||
if (this.isEmpty()) return other;
|
||||
if (other.isEmpty()) return this;
|
||||
return new MarkupTextBuilder().append(this).append(other).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a text fragment to this MarkupText.
|
||||
*
|
||||
* @param text text to be appended
|
||||
* @param kind text kind
|
||||
* @return a MarkupText that contains the content of this MarkupText and the specified text fragment.
|
||||
*/
|
||||
public MarkupText concat(@Nls String text, Kind kind) {
|
||||
if (text.isEmpty()) return this;
|
||||
return new MarkupTextBuilder().append(this).append(text, kind).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the formatting of the specified range
|
||||
*
|
||||
* @param fromInclusive start of the range (offset in characters)
|
||||
* @param toExclusive end of the range (offset in characters)
|
||||
* @param kind new highlighting kind for the range. All old highlighting in the specified range will be replaced.
|
||||
* @return a MarkupText with updated highlighting
|
||||
* @throws IllegalArgumentException if the range is invalid
|
||||
*/
|
||||
public MarkupText highlightRange(int fromInclusive, int toExclusive, Kind kind) {
|
||||
if (fromInclusive > toExclusive ||
|
||||
fromInclusive < 0) {
|
||||
throw new IllegalArgumentException("Invalid range: " + fromInclusive + ".." + toExclusive);
|
||||
}
|
||||
if (fromInclusive == toExclusive || isEmpty()) return this;
|
||||
MarkupTextBuilder newFragments = new MarkupTextBuilder();
|
||||
int start = 0;
|
||||
@Nls StringBuilder sb = new StringBuilder();
|
||||
for (Fragment fragment : fragments) {
|
||||
int end = start + fragment.text.length();
|
||||
if (end <= fromInclusive || start >= toExclusive) {
|
||||
newFragments.append(fragment);
|
||||
} else if (start < fromInclusive) {
|
||||
newFragments.append(fragment.text.substring(0, fromInclusive - start), fragment.kind);
|
||||
if (end >= toExclusive) {
|
||||
sb.append(fragment.text, fromInclusive - start, toExclusive - start);
|
||||
newFragments.append(sb.toString(), kind);
|
||||
sb.setLength(0);
|
||||
newFragments.append(fragment.text.substring(toExclusive - start), fragment.kind);
|
||||
} else {
|
||||
sb.append(fragment.text.substring(fromInclusive - start));
|
||||
}
|
||||
} else if (end >= toExclusive) {
|
||||
sb.append(fragment.text, 0, toExclusive - start);
|
||||
newFragments.append(sb.toString(), kind);
|
||||
sb.setLength(0);
|
||||
newFragments.append(fragment.text.substring(toExclusive - start), fragment.kind);
|
||||
} else {
|
||||
sb.append(fragment.text);
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
if (start < fromInclusive || start < toExclusive) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid range: " + fromInclusive + ".." + toExclusive + " for " + this + " (length=" + start + ")");
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
newFragments.append(sb.toString(), kind);
|
||||
}
|
||||
return newFragments.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MarkupText with a single plain text fragment.
|
||||
*
|
||||
* @param text text to be displayed in the UI
|
||||
* @return a MarkupText with a single plain text fragment.
|
||||
*/
|
||||
public static MarkupText plainText(@Nls String text) {
|
||||
if (text.isEmpty()) return EMPTY;
|
||||
return new MarkupText(Collections.singletonList(new Fragment(text, Kind.NORMAL)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new builder to build the MarkupText instance efficiently.
|
||||
*/
|
||||
public static MarkupTextBuilder builder() {
|
||||
return new MarkupTextBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for MarkupText.
|
||||
*/
|
||||
public static final class MarkupTextBuilder {
|
||||
private final List<Fragment> fragments = new ArrayList<>();
|
||||
|
||||
private MarkupTextBuilder() { }
|
||||
|
||||
/**
|
||||
* Appends a normal text fragment to this builder.
|
||||
*
|
||||
* @param text text to be appended
|
||||
* @return this builder
|
||||
*/
|
||||
public MarkupTextBuilder append(@Nls String text) {
|
||||
return append(text, Kind.NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a text fragment to this builder.
|
||||
*
|
||||
* @param text text to be appended
|
||||
* @param kind text kind
|
||||
* @return this builder
|
||||
*/
|
||||
public MarkupTextBuilder append(@Nls String text, Kind kind) {
|
||||
if (text.isEmpty()) return this;
|
||||
return append(new Fragment(text, kind));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a fragment to this builder.
|
||||
*
|
||||
* @param fragment fragment to be appended
|
||||
* @return this builder
|
||||
*/
|
||||
public MarkupTextBuilder append(Fragment fragment) {
|
||||
if (fragment.text.isEmpty()) return this;
|
||||
if (!fragments.isEmpty()) {
|
||||
Fragment last = fragments.get(fragments.size() - 1);
|
||||
if (last.kind == fragment.kind) {
|
||||
fragments.remove(fragments.size() - 1);
|
||||
fragment = new Fragment(last.text + fragment.text, fragment.kind);
|
||||
}
|
||||
}
|
||||
fragments.add(fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all the fragments of another MarkupText to this builder.
|
||||
*
|
||||
* @param other MarkupText to be appended
|
||||
* @return this builder
|
||||
*/
|
||||
public MarkupTextBuilder append(MarkupText other) {
|
||||
other.fragments.forEach(this::append);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a MarkupText that contains all the fragments of this builder.
|
||||
*/
|
||||
public MarkupText build() {
|
||||
if (fragments.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
return new MarkupText(Collections.unmodifiableList(new ArrayList<>(fragments)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment kind that affects its formatting.
|
||||
*/
|
||||
public enum Kind {
|
||||
/**
|
||||
* No special markup
|
||||
*/
|
||||
NORMAL,
|
||||
|
||||
/**
|
||||
* Emphasized text (likely, italic)
|
||||
*/
|
||||
EMPHASIZED,
|
||||
|
||||
/**
|
||||
* Strong text (likely, bold)
|
||||
*/
|
||||
STRONG,
|
||||
|
||||
/**
|
||||
* Underlined text
|
||||
*/
|
||||
UNDERLINED,
|
||||
|
||||
/**
|
||||
* Error text (likely, red)
|
||||
*/
|
||||
ERROR,
|
||||
|
||||
/**
|
||||
* Strikethrough text
|
||||
*/
|
||||
STRIKEOUT,
|
||||
|
||||
/**
|
||||
* Grayed out text
|
||||
*/
|
||||
GRAYED
|
||||
}
|
||||
|
||||
/**
|
||||
* A single fragment of the MarkupText. Fragments are concatenated one after another.
|
||||
*/
|
||||
public static final class Fragment {
|
||||
@Nls private final String text;
|
||||
private final Kind kind;
|
||||
|
||||
/**
|
||||
* Creates a new fragment.
|
||||
*
|
||||
* @param text text of the fragment to be displayed in UI
|
||||
* @param kind fragment kind which affects its formatting
|
||||
*/
|
||||
public Fragment(@Nls String text, Kind kind) {
|
||||
this.text = text;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return text of the fragment to be displayed in UI
|
||||
*/
|
||||
public @Nls String text() { return text; }
|
||||
|
||||
/**
|
||||
* @return fragment kind which affects its formatting
|
||||
*/
|
||||
public Kind kind() { return kind; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
Fragment that = (Fragment)obj;
|
||||
return Objects.equals(this.text, that.text) &&
|
||||
Objects.equals(this.kind, that.kind);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(text, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HTML representation of this fragment. It's assumed that a few CSS classes are defined; namely "grayed" and "error".
|
||||
*/
|
||||
public HtmlChunk toHtmlChunk() {
|
||||
switch (kind) {
|
||||
case NORMAL:
|
||||
return HtmlChunk.text(text);
|
||||
case EMPHASIZED:
|
||||
return HtmlChunk.text(text).italic();
|
||||
case STRONG:
|
||||
return HtmlChunk.text(text).bold();
|
||||
case UNDERLINED:
|
||||
return HtmlChunk.text(text).wrapWith("u");
|
||||
case ERROR:
|
||||
return HtmlChunk.text(text).wrapWith(HtmlChunk.span().setClass("error"));
|
||||
case STRIKEOUT:
|
||||
return HtmlChunk.text(text).wrapWith("s");
|
||||
case GRAYED:
|
||||
return HtmlChunk.text(text).wrapWith(HtmlChunk.span().setClass("grayed"));
|
||||
default:
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return textual representation for debug purposes only. It somehow mimics Markdown, but it's not a real Markdown.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (kind) {
|
||||
case NORMAL:
|
||||
return text;
|
||||
case EMPHASIZED:
|
||||
return "*" + text + "*";
|
||||
case STRONG:
|
||||
return "**" + text + "**";
|
||||
case UNDERLINED:
|
||||
return "_" + text + "_";
|
||||
case ERROR:
|
||||
return "!!!" + text + "!!!";
|
||||
case STRIKEOUT:
|
||||
return "~~" + text + "~~";
|
||||
case GRAYED:
|
||||
return "[" + text + "]";
|
||||
default:
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
platform/util/testSrc/com/intellij/util/text/MarkupTextTest.java
Normal file
118
platform/util/testSrc/com/intellij/util/text/MarkupTextTest.java
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.util.text;
|
||||
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.openapi.util.text.MarkupText;
|
||||
import com.intellij.openapi.util.text.MarkupText.Fragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public final class MarkupTextTest {
|
||||
@Test
|
||||
public void testCreate() {
|
||||
MarkupText markupText = MarkupText.plainText("foo");
|
||||
assertEquals("foo", markupText.toString());
|
||||
assertEquals(List.of(new Fragment("foo", MarkupText.Kind.NORMAL)), markupText.fragments());
|
||||
assertSame(MarkupText.plainText(""), MarkupText.plainText(""));
|
||||
assertSame(MarkupText.plainText(""), MarkupText.plainText("").concat("", MarkupText.Kind.GRAYED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
MarkupText markupText1 = buildLong();
|
||||
MarkupText markupText2 = buildLong();
|
||||
assertEquals(markupText1, markupText2);
|
||||
assertEquals(markupText1.hashCode(), markupText2.hashCode());
|
||||
assertEquals(markupText1.concat("", MarkupText.Kind.NORMAL), markupText2);
|
||||
assertNotEquals(markupText1.concat("1", MarkupText.Kind.NORMAL), markupText2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcat() {
|
||||
MarkupText markupText = buildLong();
|
||||
assertEquals("Hello !!!error!!! **bold** *italic* _underlined_ ~~strikeout~~ [grayed]", markupText.concat("", MarkupText.Kind.NORMAL).toString());
|
||||
assertEquals("Hello !!!error!!! **bold** *italic* _underlined_ ~~strikeout~~ [grayed]1", markupText.concat("1", MarkupText.Kind.NORMAL).toString());
|
||||
assertEquals("Hello !!!error!!! **bold** *italic* _underlined_ ~~strikeout~~ [grayed1]", markupText.concat("1", MarkupText.Kind.GRAYED).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty() {
|
||||
MarkupText markupText = buildLong();
|
||||
assertFalse(markupText.isEmpty());
|
||||
assertTrue(MarkupText.plainText("").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLength() {
|
||||
MarkupText markupText = buildLong();
|
||||
assertEquals(51, markupText.length());
|
||||
assertEquals(0, MarkupText.plainText("").length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
MarkupText markupText = buildLong();
|
||||
assertEquals("Hello !!!error!!! **bold** *italic* _underlined_ ~~strikeout~~ [grayed]", markupText.toString());
|
||||
assertEquals(List.of(new Fragment("Hello ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("error", MarkupText.Kind.ERROR),
|
||||
new Fragment(" ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("bold", MarkupText.Kind.STRONG),
|
||||
new Fragment(" ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("italic", MarkupText.Kind.EMPHASIZED),
|
||||
new Fragment(" ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("underlined", MarkupText.Kind.UNDERLINED),
|
||||
new Fragment(" ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("strikeout", MarkupText.Kind.STRIKEOUT),
|
||||
new Fragment(" ", MarkupText.Kind.NORMAL),
|
||||
new Fragment("grayed", MarkupText.Kind.GRAYED)
|
||||
), markupText.fragments());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighlight() {
|
||||
MarkupText text = MarkupText.plainText("Hello World!").highlightRange(6, 11, MarkupText.Kind.GRAYED);
|
||||
assertEquals("Hello [World]!", text.toString());
|
||||
text = text.highlightRange(3, 6, MarkupText.Kind.GRAYED);
|
||||
assertEquals("Hel[lo World]!", text.toString());
|
||||
assertEquals("Hel[lo ]~~Wor~~[ld]!", text.highlightRange(6, 9, MarkupText.Kind.STRIKEOUT).toString());
|
||||
assertEquals("Hel~~lo ~~[World]!", text.highlightRange(3, 6, MarkupText.Kind.STRIKEOUT).toString());
|
||||
assertEquals("Hel[lo Wo]~~rld~~!", text.highlightRange(8, 11, MarkupText.Kind.STRIKEOUT).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToText() {
|
||||
assertEquals("Hello error bold italic underlined strikeout grayed", buildLong().toText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHtml() {
|
||||
HtmlChunk chunk = buildLong().toHtmlChunk();
|
||||
assertEquals("Hello <span class=\"error\">error</span> <b>bold</b> <i>italic</i> <u>underlined</u> <s>strikeout</s> <span class=\"grayed\">grayed</span>",
|
||||
chunk.toString());
|
||||
}
|
||||
|
||||
private static @NotNull MarkupText buildLong() {
|
||||
MarkupText markupText = MarkupText.builder()
|
||||
.append("Hello")
|
||||
.append(" ")
|
||||
.append("error", MarkupText.Kind.ERROR)
|
||||
.append(" ")
|
||||
.append("bo", MarkupText.Kind.STRONG)
|
||||
.append("ld", MarkupText.Kind.STRONG)
|
||||
.append(" ")
|
||||
.append("")
|
||||
.append(new Fragment("italic", MarkupText.Kind.EMPHASIZED))
|
||||
.append(" ")
|
||||
.append("underlined", MarkupText.Kind.UNDERLINED)
|
||||
.append(" ")
|
||||
.append("strikeout", MarkupText.Kind.STRIKEOUT)
|
||||
.append(" ")
|
||||
.append("grayed", MarkupText.Kind.GRAYED)
|
||||
.build();
|
||||
return markupText;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user