diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7e238b79..b24d050e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -17,7 +17,6 @@ android:layout_margin="16dip" android:lineSpacingExtra="2dip" android:textSize="16sp" - android:textDirection="rtl" tools:context="ru.noties.markwon.MainActivity" tools:text="yo\nman" /> diff --git a/library/src/main/java/ru/noties/markwon/SpannableBuilder.java b/library/src/main/java/ru/noties/markwon/SpannableBuilder.java index e8715874..d9ffc46c 100644 --- a/library/src/main/java/ru/noties/markwon/SpannableBuilder.java +++ b/library/src/main/java/ru/noties/markwon/SpannableBuilder.java @@ -7,6 +7,7 @@ import android.text.Spanned; import java.util.ArrayDeque; import java.util.Deque; +import java.util.Iterator; /** * This class is used to _revert_ order of applied spans. Original SpannableStringBuilder @@ -14,6 +15,7 @@ import java.util.Deque; * will be drawn first, which leads to subtle bugs (spans receive wrong `x` values when * requested to draw itself) */ +@SuppressWarnings({"WeakerAccess", "unused"}) public class SpannableBuilder { // do not implement CharSequence (or any of Spanned interfaces) @@ -24,25 +26,12 @@ public class SpannableBuilder { private final Deque spans = new ArrayDeque<>(8); public SpannableBuilder() { - this(null); + this(""); } - public SpannableBuilder(@Nullable CharSequence cs) { - - final CharSequence text; - - if (cs != null) { - text = cs; - } else { - text = null; - } - - if (text == null) { - this.builder = new SpannableStringBuilderImpl(); - } else { - this.builder = new SpannableStringBuilderImpl(text.toString()); - copySpans(text); - } + public SpannableBuilder(@NonNull CharSequence cs) { + this.builder = new SpannableStringBuilderImpl(cs.toString()); + copySpans(cs); } /** @@ -117,6 +106,59 @@ public class SpannableBuilder { return builder.charAt(length() - 1); } + @NonNull + public CharSequence remove(int start, int end) { + + // okay: here is what we will try to do: + + final SpannableStringBuilderImpl impl = new SpannableStringBuilderImpl(builder.subSequence(start, end)); + + final Iterator iterator = spans.iterator(); + + Span span; + + while (iterator.hasNext() && ((span = iterator.next())) != null) { + if (span.start >= start && span.end <= end) { + impl.setSpan(span.what, span.start - start, span.end - start, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + iterator.remove(); + } + } + + // SHIFT EXISTING! + + if (spans.size() > 0) { + + for (Span s : spans) { + + // if end < start -> not affected + if (s.end < start) { + continue; + } + + // if end between start & end (which is really bad one) -> make end=start + if (s.end >= start && s.end <= end) { + s.end = start; + continue; + } + + // if start between start&end -> make start=end + if (s.start >= start && s.start <= end) { + s.start = start; + // shift end by difference + s.end = s.end - (end - start); + continue; + } + + // if after, just shift by difference + final int diff = end - start; + s.start = s.start - diff; + s.end = s.end - diff; + } + } + + return impl; + } + @Override @NonNull public String toString() { @@ -128,7 +170,15 @@ public class SpannableBuilder { // as we keep track of them independently). Must warn user to NOT apply inputFilters @NonNull public CharSequence text() { + + // if called once, it will apply spans, which will modify our state + applySpans(); + + // we could return here for example new SpannableStringBuilder(builder) + // but, if returned value will be used in other SpannableBuilder, + // we won't be able to detect in what order to store the spans + return builder; } @@ -173,8 +223,8 @@ public class SpannableBuilder { private static class Span { final Object what; - final int start; - final int end; + int start; + int end; final int flags; Span(@NonNull Object what, int start, int end, int flags) { diff --git a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java index e104d5fd..c6a8cc93 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java +++ b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java @@ -61,7 +61,6 @@ import ru.noties.markwon.tasklist.TaskListItem; public class SpannableMarkdownVisitor extends AbstractVisitor { private final SpannableConfiguration configuration; - // private final SpannableStringBuilder builder; private final SpannableBuilder builder; private final Deque htmlInlineItems; @@ -321,10 +320,6 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { private boolean handleTableNodes(CustomNode node) { - if (true) { - return false; - } - final boolean handled; if (node instanceof TableBody) { @@ -367,11 +362,10 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { pendingTableRow = new ArrayList<>(2); } -// pendingTableRow.add(new TableRowSpan.Cell( -// tableCellAlignment(cell.getAlignment()), -// builder.subSequence(length, builder.length()) -// )); -// builder.replace(length, builder.length(), ""); + pendingTableRow.add(new TableRowSpan.Cell( + tableCellAlignment(cell.getAlignment()), + builder.remove(length, builder.length()) + )); tableRowIsHeader = cell.isHeader();