Merge with 2.0.2 changes

This commit is contained in:
Dimitry Ivanov 2019-03-15 15:48:01 +03:00
commit 421fc95d6f
6 changed files with 145 additions and 9 deletions

View File

@ -61,14 +61,28 @@ public class BulletListItemSpan implements LeadingMarginSpan {
final int marginLeft = (width - side) / 2; final int marginLeft = (width - side) / 2;
// @since 2.0.2
// There is a bug in Android Nougat, when this span receives an `x` that
// doesn't correspond to what it should be (text is placed correctly though).
// Let's make this a general rule -> manually calculate difference between expected/actual
// and add this difference to resulting left/right values. If everything goes well
// we do not encounter a bug -> this `diff` value will be 0
final int diff;
if (dir < 0) {
// rtl
diff = x - (layout.getWidth() - (width * level));
} else {
diff = (width * level) - x;
}
// in order to support RTL // in order to support RTL
final int l; final int l;
final int r; final int r;
{ {
final int left = x + (dir * marginLeft); final int left = x + (dir * marginLeft);
final int right = left + (dir * side); final int right = left + (dir * side);
l = Math.min(left, right); l = Math.min(left, right) + (dir * diff);
r = Math.max(left, right); r = Math.max(left, right) + (dir * diff);
} }
final int t = baseline + (int) ((paint.descent() + paint.ascent()) / 2.F + .5F) - (side / 2); final int t = baseline + (int) ((paint.descent() + paint.ascent()) / 2.F + .5F) - (side / 2);

View File

@ -15,6 +15,15 @@ android {
dependencies { dependencies {
api project(':markwon-core') api project(':markwon-core')
deps['test'].with {
testImplementation project(':markwon-test-span')
testImplementation it['junit']
testImplementation it['robolectric']
testImplementation it['commons-io']
}
} }
registerArtifact(this) registerArtifact(this)

View File

@ -23,7 +23,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
class TaskListBlockParser extends AbstractBlockParser { class TaskListBlockParser extends AbstractBlockParser {
private static final Pattern PATTERN = Pattern.compile("\\s*-\\s+\\[(x|X|\\s)\\]\\s+(.*)"); private static final Pattern PATTERN = Pattern.compile("\\s*([-*+]|\\d{1,9}[.)])\\s+\\[(x|X|\\s)]\\s+(.*)");
private final TaskListBlock block = new TaskListBlock(); private final TaskListBlock block = new TaskListBlock();
@ -88,9 +88,9 @@ class TaskListBlockParser extends AbstractBlockParser {
continue; continue;
} }
listItem = new TaskListItem() listItem = new TaskListItem()
.done(isDone(matcher.group(1))) .done(isDone(matcher.group(2)))
.indent(item.indent / 2); .indent(item.indent / 2);
inlineParser.parse(matcher.group(2), listItem); inlineParser.parse(matcher.group(3), listItem);
block.appendChild(listItem); block.appendChild(listItem);
} }
} }

View File

@ -0,0 +1,101 @@
package ru.noties.markwon.ext.tasklist;
import android.support.annotation.NonNull;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.MarkwonConfiguration;
import ru.noties.markwon.MarkwonSpansFactory;
import ru.noties.markwon.RenderProps;
import ru.noties.markwon.SpanFactory;
import ru.noties.markwon.test.TestSpan;
import ru.noties.markwon.test.TestSpanMatcher;
import static ru.noties.markwon.test.TestSpan.args;
import static ru.noties.markwon.test.TestSpan.document;
import static ru.noties.markwon.test.TestSpan.span;
import static ru.noties.markwon.test.TestSpan.text;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class TaskListTest {
private static final String SPAN = "task-list";
private static final String IS_DONE = "is-done";
@Test
public void test() {
final TestSpan.Document document = document(
span(SPAN, args(IS_DONE, false), text("First")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Second")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Third")),
newLine(),
span(SPAN, args(IS_DONE, false), text("First star")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Second star")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Third star")),
newLine(),
span(SPAN, args(IS_DONE, false), text("First plus")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Second plus")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Third plus")),
newLine(),
span(SPAN, args(IS_DONE, true), text("Number with dot")),
newLine(),
span(SPAN, args(IS_DONE, false), text("Number"))
);
TestSpanMatcher.matches(
markwon().toMarkdown(read("task-lists.md")),
document
);
}
@NonNull
private static Markwon markwon() {
return Markwon.builder(RuntimeEnvironment.application)
.usePlugin(TaskListPlugin.create(RuntimeEnvironment.application))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
builder.setFactory(TaskListItem.class, new SpanFactory() {
@Override
public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
return span(SPAN, args(IS_DONE, TaskListProps.DONE.require(props)));
}
});
}
})
.build();
}
@SuppressWarnings("SameParameterValue")
@NonNull
private static String read(@NonNull String name) {
try {
return IOUtils.resourceToString("tests/" + name, StandardCharsets.UTF_8, TaskListDrawable.class.getClassLoader());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@NonNull
private static TestSpan.Text newLine() {
return text("\n");
}
}

View File

@ -0,0 +1,11 @@
- [ ] First
- [x] Second
- [X] Third
* [ ] First star
* [x] Second star
* [X] Third star
+ [ ] First plus
+ [x] Second plus
+ [X] Third plus
1. [x] Number with dot
3) [ ] Number

View File

@ -3,8 +3,9 @@ package ru.noties.markwon.test;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.Spanned; import android.text.Spanned;
import junit.framework.Assert;
import junit.framework.ComparisonFailure; import org.junit.Assert;
import org.junit.ComparisonFailure;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -106,8 +107,8 @@ public abstract class TestSpanMatcher {
} }
throw new AssertionError( throw new AssertionError(
String.format(Locale.US, "Expected span{%s} at {start: %d, end: %d}, found: %s", String.format(Locale.US, "Expected span{%s} at {start: %d, end: %d}, found: %s, text: \"%s\"",
expectedSpan, start, end, actualSpan)); expectedSpan, start, end, actualSpan, spanned.subSequence(start, end)));
} }
} }