Redefined test format
This commit is contained in:
parent
db4be0eee3
commit
caf7f99335
@ -9,7 +9,6 @@ import org.junit.runner.RunWith;
|
|||||||
import org.robolectric.ParameterizedRobolectricTestRunner;
|
import org.robolectric.ParameterizedRobolectricTestRunner;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import ix.Ix;
|
import ix.Ix;
|
||||||
@ -54,65 +53,81 @@ public class SpannableMarkdownVisitorTest {
|
|||||||
node.accept(visitor);
|
node.accept(visitor);
|
||||||
|
|
||||||
final SpannableStringBuilder stringBuilder = builder.spannableStringBuilder();
|
final SpannableStringBuilder stringBuilder = builder.spannableStringBuilder();
|
||||||
final String raw = stringBuilder.toString();
|
|
||||||
|
System.out.printf("%n%s%n", stringBuilder);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int lastIndex = 0;
|
|
||||||
|
|
||||||
for (TestEntry entry : data.output()) {
|
for (TestNode testNode : data.output()) {
|
||||||
|
index = validate(stringBuilder, index, testNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final String expected = entry.text();
|
private int validate(@NonNull SpannableStringBuilder builder, int index, @NonNull TestNode node) {
|
||||||
|
|
||||||
final boolean isText = "text".equals(entry.name());
|
if (node.isText()) {
|
||||||
|
|
||||||
final int start;
|
final String text;
|
||||||
final int end;
|
{
|
||||||
|
final String content = node.getAsText().text();
|
||||||
|
|
||||||
if (isText) {
|
// code is a special case as we wrap it around non-breakable spaces
|
||||||
start = lastIndex;
|
final TestNode parent = node.parent();
|
||||||
end = start + expected.length();
|
if (parent != null) {
|
||||||
index = lastIndex = end;
|
final TestNode.Span span = parent.getAsSpan();
|
||||||
|
if (TestSpan.CODE.equals(span.name())) {
|
||||||
|
text = "\u00a0" + content + "\u00a0";
|
||||||
|
} else if (TestSpan.CODE_BLOCK.equals(span.name())) {
|
||||||
|
text = "\u00a0\n" + content + "\n\u00a0";
|
||||||
} else {
|
} else {
|
||||||
start = raw.indexOf(expected, index);
|
text = content;
|
||||||
if (start < 0) {
|
|
||||||
throw new AssertionError(String.format("Cannot find `%s` starting at index: %d, raw: %n###%n%s%n###",
|
|
||||||
expected, start, raw
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
end = start + expected.length();
|
|
||||||
lastIndex = Math.max(end, lastIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!expected.equals(raw.substring(start, end))) {
|
|
||||||
throw new AssertionError(String.format("Expected: `%s`, actual: `%s`, start: %d, raw: %n###%n%s%n###",
|
|
||||||
expected, raw.substring(start, end), start, raw
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object[] spans = stringBuilder.getSpans(start, end, Object.class);
|
|
||||||
final int length = spans != null ? spans.length : 0;
|
|
||||||
|
|
||||||
if (isText) {
|
|
||||||
// validate no spans
|
|
||||||
assertEquals(Arrays.toString(spans), 0, length);
|
|
||||||
} else {
|
} else {
|
||||||
assertTrue(length > 0);
|
text = content;
|
||||||
final Object span = Ix.fromArray(spans)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(text, builder.subSequence(index, index + text.length()).toString());
|
||||||
|
|
||||||
|
return index + text.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
final TestNode.Span span = node.getAsSpan();
|
||||||
|
|
||||||
|
int out = index;
|
||||||
|
|
||||||
|
for (TestNode child : span.children()) {
|
||||||
|
out = validate(builder, out, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String info = node.toString();
|
||||||
|
|
||||||
|
// we can possibly have parent spans here, should filter them
|
||||||
|
final Object[] spans = builder.getSpans(index, out, Object.class);
|
||||||
|
assertTrue(info, spans != null);
|
||||||
|
|
||||||
|
final TestSpan testSpan = Ix.fromArray(spans)
|
||||||
.filter(new IxPredicate<Object>() {
|
.filter(new IxPredicate<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Object o) {
|
public boolean test(Object o) {
|
||||||
return start == stringBuilder.getSpanStart(o)
|
return o instanceof TestSpan;
|
||||||
&& end == stringBuilder.getSpanEnd(o);
|
}
|
||||||
|
})
|
||||||
|
.cast(TestSpan.class)
|
||||||
|
.filter(new IxPredicate<TestSpan>() {
|
||||||
|
@Override
|
||||||
|
public boolean test(TestSpan testSpan) {
|
||||||
|
return span.name().equals(testSpan.name());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.first(null);
|
.first(null);
|
||||||
assertNotNull(span);
|
|
||||||
assertTrue(span instanceof TestSpan);
|
assertNotNull(info, testSpan);
|
||||||
final TestSpan testSpan = (TestSpan) span;
|
|
||||||
assertEquals(entry.name(), testSpan.name());
|
assertEquals(info, span.name(), testSpan.name());
|
||||||
assertEquals(entry.attributes(), testSpan.attributes());
|
assertEquals(info, span.attributes(), testSpan.attributes());
|
||||||
}
|
|
||||||
}
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -126,7 +141,5 @@ public class SpannableMarkdownVisitorTest {
|
|||||||
.linkResolver(mock(LinkResolverDef.class))
|
.linkResolver(mock(LinkResolverDef.class))
|
||||||
.factory(factory)
|
.factory(factory)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// return configuration;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,13 +10,13 @@ class TestData {
|
|||||||
private final String description;
|
private final String description;
|
||||||
private final String input;
|
private final String input;
|
||||||
private final TestConfig config;
|
private final TestConfig config;
|
||||||
private final List<TestEntry> output;
|
private final List<TestNode> output;
|
||||||
|
|
||||||
TestData(
|
TestData(
|
||||||
@Nullable String description,
|
@Nullable String description,
|
||||||
@NonNull String input,
|
@NonNull String input,
|
||||||
@NonNull TestConfig config,
|
@NonNull TestConfig config,
|
||||||
@NonNull List<TestEntry> output) {
|
@NonNull List<TestNode> output) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@ -39,7 +39,7 @@ class TestData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<TestEntry> output() {
|
public List<TestNode> output() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,9 @@ abstract class TestDataReader {
|
|||||||
|
|
||||||
static class Reader {
|
static class Reader {
|
||||||
|
|
||||||
|
private static final String ATTRS = "attrs";
|
||||||
|
private static final String TEXT = "text";
|
||||||
|
|
||||||
private final String file;
|
private final String file;
|
||||||
|
|
||||||
Reader(@NonNull String file) {
|
Reader(@NonNull String file) {
|
||||||
@ -120,95 +123,99 @@ abstract class TestDataReader {
|
|||||||
|
|
||||||
final String input = jsonObject.get("input").getAsString();
|
final String input = jsonObject.get("input").getAsString();
|
||||||
if (TextUtils.isEmpty(input)) {
|
if (TextUtils.isEmpty(input)) {
|
||||||
throw new RuntimeException(String.format("Test case file `%s` is missing input parameter", file));
|
throw new RuntimeException(String.format("Test case file `%s` is missing " +
|
||||||
|
"input parameter", file));
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<TestEntry> testSpans = testEntries(jsonObject.get("output").getAsJsonArray());
|
final TestConfig testConfig = testConfig(jsonObject.get("config"));
|
||||||
if (testSpans.size() == 0) {
|
|
||||||
throw new RuntimeException(String.format("Test case file `%s` has no output specified", file));
|
final List<TestNode> testNodes = testNodes(jsonObject.get("output").getAsJsonArray());
|
||||||
|
if (testNodes.size() == 0) {
|
||||||
|
throw new RuntimeException(String.format("Test case file `%s` has no " +
|
||||||
|
"output specified", file));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TestData(
|
return new TestData(
|
||||||
description,
|
description,
|
||||||
input,
|
input,
|
||||||
testConfig(jsonObject.get("config")),
|
testConfig,
|
||||||
testSpans
|
testNodes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: rename TestNode -> it's not a node... but... what?
|
@NonNull
|
||||||
|
private List<TestNode> testNodes(@NonNull JsonArray array) {
|
||||||
|
return testNodes(null, array);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<TestEntry> testEntries(@NonNull JsonArray array) {
|
private List<TestNode> testNodes(@Nullable TestNode parent, @NonNull JsonArray array) {
|
||||||
|
|
||||||
// all items are contained in this array
|
// an item in array is a JsonObject
|
||||||
// key is the name of an item
|
|
||||||
// item can be defined like this:
|
|
||||||
// link: "text-content-of-the-link"
|
|
||||||
// link:
|
|
||||||
// attributes:
|
|
||||||
// - href: "my-href-attribute"
|
|
||||||
// text: "and here is the text content"
|
|
||||||
// text node can be found only at root level
|
|
||||||
|
|
||||||
final int length = array.size();
|
// it can be "b": "bold" -> means Span(name="b", children=[Text(bold)]
|
||||||
|
// or b:
|
||||||
|
// - text: "bold" -> which is the same as above
|
||||||
|
|
||||||
final List<TestEntry> testSpans = new ArrayList<>(length);
|
// it can additionally contain "attrs" key which is the attributes
|
||||||
|
// b:
|
||||||
|
// - text: "bold"
|
||||||
|
// attrs:
|
||||||
|
// href: "my-href"
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
final int size = array.size();
|
||||||
|
|
||||||
final JsonElement element = array.get(i);
|
final List<TestNode> testNodes = new ArrayList<>(size);
|
||||||
|
|
||||||
if (element.isJsonObject()) {
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
||||||
final JsonObject object = element.getAsJsonObject();
|
final JsonObject object = array.get(i).getAsJsonObject();
|
||||||
|
|
||||||
// objects must have exactly 1 key: name of the node
|
String name = null;
|
||||||
// it's value can be different: JsonPrimitive (String) or an JsonObject (with attributes and text)
|
Map<String, String> attributes = null;
|
||||||
|
|
||||||
final String name = object.keySet().iterator().next();
|
|
||||||
final JsonElement value = object.get(name);
|
|
||||||
|
|
||||||
final String text;
|
|
||||||
final Map<String, String> attributes;
|
|
||||||
|
|
||||||
if (value.isJsonObject()) {
|
|
||||||
|
|
||||||
final JsonObject valueObject = value.getAsJsonObject();
|
|
||||||
text = valueObject.get("text").getAsString();
|
|
||||||
attributes = attributes(valueObject.get("attrs"));
|
|
||||||
|
|
||||||
|
for (String key : object.keySet()) {
|
||||||
|
if (ATTRS.equals(key)) {
|
||||||
|
attributes = attributes(object.get(key));
|
||||||
|
} else if (name == null) {
|
||||||
|
name = key;
|
||||||
} else {
|
} else {
|
||||||
|
// we allow only 2 keys: span and/or attributes and no more
|
||||||
final JsonPrimitive primitive;
|
throw new RuntimeException("Unexpected key in object: " + object);
|
||||||
|
}
|
||||||
if (value.isJsonPrimitive()) {
|
|
||||||
primitive = value.getAsJsonPrimitive();
|
|
||||||
} else {
|
|
||||||
primitive = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primitive == null
|
if (name == null) {
|
||||||
|| !primitive.isString()) {
|
throw new RuntimeException("Object is missing tag name: " + object);
|
||||||
throw new RuntimeException(String.format("Unexpected json element at index: `%d` in array: `%s`",
|
|
||||||
i, array
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text = primitive.getAsString();
|
if (attributes == null) {
|
||||||
attributes = Collections.emptyMap();
|
attributes = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
testSpans.add(new TestEntry(name, text, attributes));
|
final JsonElement element = object.get(name);
|
||||||
|
|
||||||
|
if (TEXT.equals(name)) {
|
||||||
|
testNodes.add(new TestNode.Text(parent, element.getAsString()));
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(String.format("Unexpected json element at index: `%d` in array: `%s`",
|
|
||||||
i, array
|
final List<TestNode> children = new ArrayList<>(1);
|
||||||
));
|
final TestNode.Span span = new TestNode.Span(parent, name, children, attributes);
|
||||||
|
|
||||||
|
// if it's primitive string -> just append text node
|
||||||
|
if (element.isJsonPrimitive()) {
|
||||||
|
children.add(new TestNode.Text(span, element.getAsString()));
|
||||||
|
} else if (element.isJsonArray()) {
|
||||||
|
children.addAll(testNodes(span, element.getAsJsonArray()));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unexpected element: " + object);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNodes.add(span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return testSpans;
|
return testNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
package ru.noties.markwon.renderer.visitor;
|
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TestEntry {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final String text;
|
|
||||||
private final Map<String, String> attributes;
|
|
||||||
|
|
||||||
TestEntry(@NonNull String name, @NonNull String text, @NonNull Map<String, String> attributes) {
|
|
||||||
this.name = name;
|
|
||||||
this.text = text;
|
|
||||||
this.attributes = attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String text() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Map<String, String> attributes() {
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TestEntry{" +
|
|
||||||
"name='" + name + '\'' +
|
|
||||||
", text='" + text + '\'' +
|
|
||||||
", attributes=" + attributes +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,6 +19,7 @@ import ru.noties.markwon.spans.TableRowSpan;
|
|||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.BLOCK_QUOTE;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.BLOCK_QUOTE;
|
||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.BULLET_LIST;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.BULLET_LIST;
|
||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.CODE;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.CODE;
|
||||||
|
import static ru.noties.markwon.renderer.visitor.TestSpan.CODE_BLOCK;
|
||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.EMPHASIS;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.EMPHASIS;
|
||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.HEADING;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.HEADING;
|
||||||
import static ru.noties.markwon.renderer.visitor.TestSpan.IMAGE;
|
import static ru.noties.markwon.renderer.visitor.TestSpan.IMAGE;
|
||||||
@ -63,13 +64,16 @@ class TestFactory implements SpannableFactory {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Object code(@NonNull SpannableTheme theme, boolean multiline) {
|
public Object code(@NonNull SpannableTheme theme, boolean multiline) {
|
||||||
return new TestSpan(CODE, map("multiline", multiline));
|
final String name = multiline
|
||||||
|
? CODE_BLOCK
|
||||||
|
: CODE;
|
||||||
|
return new TestSpan(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Object orderedListItem(@NonNull SpannableTheme theme, int startNumber) {
|
public Object orderedListItem(@NonNull SpannableTheme theme, int startNumber) {
|
||||||
return new TestSpan(ORDERED_LIST, map("startNumber", startNumber));
|
return new TestSpan(ORDERED_LIST, map("start", startNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -87,7 +91,7 @@ class TestFactory implements SpannableFactory {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Object heading(@NonNull SpannableTheme theme, int level) {
|
public Object heading(@NonNull SpannableTheme theme, int level) {
|
||||||
return new TestSpan(HEADING, map("level", level));
|
return new TestSpan(HEADING + level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -101,7 +105,7 @@ class TestFactory implements SpannableFactory {
|
|||||||
public Object taskListItem(@NonNull SpannableTheme theme, int blockIndent, boolean isDone) {
|
public Object taskListItem(@NonNull SpannableTheme theme, int blockIndent, boolean isDone) {
|
||||||
return new TestSpan(TASK_LIST, map(
|
return new TestSpan(TASK_LIST, map(
|
||||||
Pair.of("blockIdent", blockIndent),
|
Pair.of("blockIdent", blockIndent),
|
||||||
Pair.of("isDone", isDone)
|
Pair.of("done", isDone)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,8 +114,8 @@ class TestFactory implements SpannableFactory {
|
|||||||
public Object tableRow(@NonNull SpannableTheme theme, @NonNull List<TableRowSpan.Cell> cells, boolean isHeader, boolean isOdd) {
|
public Object tableRow(@NonNull SpannableTheme theme, @NonNull List<TableRowSpan.Cell> cells, boolean isHeader, boolean isOdd) {
|
||||||
return new TestSpan(TABLE_ROW, map(
|
return new TestSpan(TABLE_ROW, map(
|
||||||
Pair.of("cells", cells),
|
Pair.of("cells", cells),
|
||||||
Pair.of("isHeader", isHeader),
|
Pair.of("header", isHeader),
|
||||||
Pair.of("isOdd", isOdd)
|
Pair.of("odd", isOdd)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +131,7 @@ class TestFactory implements SpannableFactory {
|
|||||||
@Override
|
@Override
|
||||||
public Object image(@NonNull SpannableTheme theme, @NonNull String destination, @NonNull AsyncDrawable.Loader loader, @NonNull ImageSizeResolver imageSizeResolver, @Nullable ImageSize imageSize, boolean replacementTextIsLink) {
|
public Object image(@NonNull SpannableTheme theme, @NonNull String destination, @NonNull AsyncDrawable.Loader loader, @NonNull ImageSizeResolver imageSizeResolver, @Nullable ImageSize imageSize, boolean replacementTextIsLink) {
|
||||||
return new TestSpan(IMAGE, map(
|
return new TestSpan(IMAGE, map(
|
||||||
Pair.of("destination", destination),
|
Pair.of("src", destination),
|
||||||
Pair.of("imageSize", imageSize),
|
Pair.of("imageSize", imageSize),
|
||||||
Pair.of("replacementTextIsLink", replacementTextIsLink)
|
Pair.of("replacementTextIsLink", replacementTextIsLink)
|
||||||
));
|
));
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
package ru.noties.markwon.renderer.visitor;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
abstract class TestNode {
|
||||||
|
|
||||||
|
private final TestNode parent;
|
||||||
|
|
||||||
|
TestNode(@Nullable TestNode parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public TestNode parent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract boolean isText();
|
||||||
|
|
||||||
|
abstract boolean isSpan();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
abstract Text getAsText();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
abstract Span getAsSpan();
|
||||||
|
|
||||||
|
|
||||||
|
static class Text extends TestNode {
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
Text(@Nullable TestNode parent, @NonNull String text) {
|
||||||
|
super(parent);
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String text() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isText() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isSpan() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
Text getAsText() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
Span getAsSpan() {
|
||||||
|
throw new ClassCastException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Text{" +
|
||||||
|
"text='" + text + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Span extends TestNode {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final List<TestNode> children;
|
||||||
|
private final Map<String, String> attributes;
|
||||||
|
|
||||||
|
Span(
|
||||||
|
@Nullable TestNode parent,
|
||||||
|
@NonNull String name,
|
||||||
|
@NonNull List<TestNode> children,
|
||||||
|
@NonNull Map<String, String> attributes) {
|
||||||
|
super(parent);
|
||||||
|
this.name = name;
|
||||||
|
this.children = children;
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public List<TestNode> children() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Map<String, String> attributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isText() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isSpan() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
Text getAsText() {
|
||||||
|
throw new ClassCastException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
Span getAsSpan() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Span{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
", children=" + children +
|
||||||
|
", attributes=" + attributes +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ class TestSpan {
|
|||||||
static final String EMPHASIS = "i";
|
static final String EMPHASIS = "i";
|
||||||
static final String BLOCK_QUOTE = "blockquote";
|
static final String BLOCK_QUOTE = "blockquote";
|
||||||
static final String CODE = "code";
|
static final String CODE = "code";
|
||||||
|
static final String CODE_BLOCK = "code-block";
|
||||||
static final String ORDERED_LIST = "ol";
|
static final String ORDERED_LIST = "ol";
|
||||||
static final String BULLET_LIST = "ul";
|
static final String BULLET_LIST = "ul";
|
||||||
static final String THEMATIC_BREAK = "hr";
|
static final String THEMATIC_BREAK = "hr";
|
||||||
|
@ -13,11 +13,13 @@ config:
|
|||||||
output:
|
output:
|
||||||
- text: "Here is some "
|
- text: "Here is some "
|
||||||
- a:
|
- a:
|
||||||
|
- text: "link"
|
||||||
attrs:
|
attrs:
|
||||||
href: "https://my.href"
|
href: "https://my.href"
|
||||||
text: "link"
|
|
||||||
- text: " "
|
- text: " "
|
||||||
- b: "bold bold italic bold"
|
- b:
|
||||||
- i: "bold italic"
|
- text: "bold "
|
||||||
|
- i: "bold italic" #equals to: `- i: - text: "bold italic"`
|
||||||
|
- text: " bold"
|
||||||
- text: " normal"
|
- text: " normal"
|
||||||
|
|
||||||
|
@ -16,10 +16,17 @@ input: |-
|
|||||||
output:
|
output:
|
||||||
- text: "First "
|
- text: "First "
|
||||||
- b: "line"
|
- b: "line"
|
||||||
- text: " "
|
- text: " is "
|
||||||
- i: "always"
|
- i: "always"
|
||||||
- text: " "
|
- text: " "
|
||||||
- s: "strike"
|
- s: "strike"
|
||||||
- text: " down\n\n"
|
- text: " down\n\n"
|
||||||
- blockquote: "Some quote here!"
|
- blockquote: "Some quote here!"
|
||||||
- text: "\n\n"
|
- text: "\n\n"
|
||||||
|
- h1: "Header 1"
|
||||||
|
- text: "\n\n"
|
||||||
|
- h2: "Header 2"
|
||||||
|
- text: "\n\nand "
|
||||||
|
- code: "some code"
|
||||||
|
- text: " and more:\n\n"
|
||||||
|
- code-block: "the code in multiline"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user