Core functionality plugin
This commit is contained in:
parent
498c811987
commit
3526e16565
@ -41,17 +41,17 @@
|
||||
<!--<data-->
|
||||
<!--android:host="*"-->
|
||||
<!--android:scheme="http"-->
|
||||
<!--android:mimeType="text/markdown"/>-->
|
||||
<!--android:mimeType="text/toMarkdown"/>-->
|
||||
|
||||
<!--<data-->
|
||||
<!--android:host="*"-->
|
||||
<!--android:scheme="file"-->
|
||||
<!--android:mimeType="text/markdown"/>-->
|
||||
<!--android:mimeType="text/toMarkdown"/>-->
|
||||
|
||||
<!--<data-->
|
||||
<!--android:host="*"-->
|
||||
<!--android:scheme="https"-->
|
||||
<!--android:mimeType="text/markdown"/>-->
|
||||
<!--android:mimeType="text/toMarkdown"/>-->
|
||||
|
||||
<data android:pathPattern=".*\\.markdown" />
|
||||
<data android:pathPattern=".*\\.mdown" />
|
||||
|
@ -71,7 +71,7 @@ public class MainActivity extends Activity {
|
||||
.use(new CorePlugin())
|
||||
.use(TaskListPlugin.create(new TaskListDrawable(0xffff0000, 0xffff0000, -1)))
|
||||
.build();
|
||||
final CharSequence markdown = markwon2.markdown("**hello _dear_** `code`\n\n- [ ] first\n- [x] second");
|
||||
final CharSequence markdown = markwon2.toMarkdown("**hello _dear_** `code`\n\n- [ ] first\n- [x] second");
|
||||
textView.setText(markdown);
|
||||
return;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class MarkdownRenderer {
|
||||
|
||||
final long end = SystemClock.uptimeMillis();
|
||||
|
||||
Debug.i("markdown rendered: %d ms", end - start);
|
||||
Debug.i("toMarkdown rendered: %d ms", end - start);
|
||||
|
||||
if (!isCancelled()) {
|
||||
handler.post(new Runnable() {
|
||||
|
@ -60,7 +60,7 @@ public class MarkwonViewHelper implements IMarkwonView {
|
||||
this.provider = provider;
|
||||
this.configuration = provider.provide(textView.getContext());
|
||||
if (!TextUtils.isEmpty(markdown)) {
|
||||
// invalidate rendered markdown
|
||||
// invalidate rendered toMarkdown
|
||||
setMarkdown(markdown);
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ public abstract class AbstractMarkwonPlugin implements MarkwonPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) {
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) {
|
||||
public void afterSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -48,12 +48,12 @@ public abstract class Markwon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses submitted raw markdown, converts it to CharSequence (with Spannables)
|
||||
* Parses submitted raw toMarkdown, converts it to CharSequence (with Spannables)
|
||||
* and applies it to view
|
||||
*
|
||||
* @param view {@link TextView} to set markdown into
|
||||
* @param view {@link TextView} to set toMarkdown into
|
||||
* @param configuration a {@link MarkwonConfiguration} instance
|
||||
* @param markdown raw markdown String (for example: {@code `**Hello**`})
|
||||
* @param markdown raw toMarkdown String (for example: {@code `**Hello**`})
|
||||
* @see #markdown(MarkwonConfiguration, String)
|
||||
* @see #setText(TextView, CharSequence)
|
||||
* @see MarkwonConfiguration
|
||||
@ -69,13 +69,13 @@ public abstract class Markwon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to apply parsed markdown.
|
||||
* Helper method to apply parsed toMarkdown.
|
||||
* <p>
|
||||
* Since 1.0.6 redirects it\'s call to {@link #setText(TextView, CharSequence, MovementMethod)}
|
||||
* with LinkMovementMethod as an argument to preserve current API.
|
||||
*
|
||||
* @param view {@link TextView} to set markdown into
|
||||
* @param text parsed markdown
|
||||
* @param view {@link TextView} to set toMarkdown into
|
||||
* @param text parsed toMarkdown
|
||||
* @see #setText(TextView, CharSequence, MovementMethod)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ -84,13 +84,13 @@ public abstract class Markwon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to apply parsed markdown with additional argument of a MovementMethod. Used
|
||||
* Helper method to apply parsed toMarkdown with additional argument of a MovementMethod. Used
|
||||
* to workaround problems that occur when using system LinkMovementMethod (for example:
|
||||
* https://issuetracker.google.com/issues/37068143). As a better alternative to it consider
|
||||
* using: https://github.com/saket/Better-Link-Movement-Method
|
||||
*
|
||||
* @param view TextView to set markdown into
|
||||
* @param text parsed markdown
|
||||
* @param view TextView to set toMarkdown into
|
||||
* @param text parsed toMarkdown
|
||||
* @param movementMethod an implementation if MovementMethod or null
|
||||
* @see #scheduleDrawables(TextView)
|
||||
* @see #scheduleTableRows(TextView)
|
||||
@ -102,7 +102,7 @@ public abstract class Markwon {
|
||||
unscheduleTableRows(view);
|
||||
|
||||
// @since 2.0.1 we must measure ordered-list-item-spans before applying text to a TextView.
|
||||
// if markdown has a lot of ordered list items (or text size is relatively big, or block-margin
|
||||
// if toMarkdown has a lot of ordered list items (or text size is relatively big, or block-margin
|
||||
// is relatively small) then this list won't be rendered properly: it will take correct
|
||||
// layout (width and margin) but will be clipped if margin is not _consistent_ between calls.
|
||||
OrderedListItemSpan.measure(view, text);
|
||||
@ -117,11 +117,11 @@ public abstract class Markwon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns parsed markdown with default {@link MarkwonConfiguration} obtained from {@link Context}
|
||||
* Returns parsed toMarkdown with default {@link MarkwonConfiguration} obtained from {@link Context}
|
||||
*
|
||||
* @param context {@link Context}
|
||||
* @param markdown raw markdown
|
||||
* @return parsed markdown
|
||||
* @param markdown raw toMarkdown
|
||||
* @return parsed toMarkdown
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NonNull
|
||||
@ -131,11 +131,11 @@ public abstract class Markwon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns parsed markdown with provided {@link MarkwonConfiguration}
|
||||
* Returns parsed toMarkdown with provided {@link MarkwonConfiguration}
|
||||
*
|
||||
* @param configuration a {@link MarkwonConfiguration}
|
||||
* @param markdown raw markdown
|
||||
* @return parsed markdown
|
||||
* @param markdown raw toMarkdown
|
||||
* @return parsed toMarkdown
|
||||
* @see MarkwonConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
@ -2,6 +2,7 @@ package ru.noties.markwon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
|
||||
@ -18,8 +19,13 @@ public abstract class Markwon2 {
|
||||
@NonNull
|
||||
public abstract CharSequence render(@NonNull Node node);
|
||||
|
||||
// parse + render
|
||||
@NonNull
|
||||
public abstract CharSequence markdown(@NonNull String input);
|
||||
public abstract CharSequence toMarkdown(@NonNull String input);
|
||||
|
||||
public abstract void setMarkdown(@NonNull TextView textView, @NonNull String markdown);
|
||||
|
||||
public abstract void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown);
|
||||
|
||||
public interface Builder {
|
||||
|
||||
|
@ -46,7 +46,7 @@ class MarkwonBuilderImpl implements Markwon2.Builder {
|
||||
|
||||
return new MarkwonImpl(
|
||||
parserBuilder.build(),
|
||||
visitorBuilder.build(themeBuilder.build(), configurationBuilder.build()),
|
||||
visitorBuilder.build(configurationBuilder.build(themeBuilder.build())),
|
||||
Collections.unmodifiableList(plugins)
|
||||
);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class MarkwonConfiguration {
|
||||
// creates default configuration
|
||||
@NonNull
|
||||
public static MarkwonConfiguration create(@NonNull Context context) {
|
||||
return new Builder(context).build();
|
||||
return new Builder(context).build(MarkwonTheme.create(context));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -28,9 +28,8 @@ public class MarkwonConfiguration {
|
||||
return new Builder(context);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private final MarkwonTheme theme;
|
||||
|
||||
private final MarkwonTheme theme;
|
||||
private final AsyncDrawable.Loader asyncDrawableLoader;
|
||||
private final SyntaxHighlight syntaxHighlight;
|
||||
private final LinkSpan.Resolver linkResolver;
|
||||
@ -65,7 +64,6 @@ public class MarkwonConfiguration {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Deprecated
|
||||
public MarkwonTheme theme() {
|
||||
return theme;
|
||||
}
|
||||
@ -137,7 +135,6 @@ public class MarkwonConfiguration {
|
||||
|
||||
private final Context context;
|
||||
|
||||
@Deprecated
|
||||
private MarkwonTheme theme;
|
||||
private AsyncDrawable.Loader asyncDrawableLoader;
|
||||
private SyntaxHighlight syntaxHighlight;
|
||||
@ -169,12 +166,12 @@ public class MarkwonConfiguration {
|
||||
this.htmlAllowNonClosedTags = configuration.htmlAllowNonClosedTags;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Deprecated
|
||||
public Builder theme(@NonNull MarkwonTheme theme) {
|
||||
this.theme = theme;
|
||||
return this;
|
||||
}
|
||||
// @NonNull
|
||||
// @Deprecated
|
||||
// public Builder theme(@NonNull MarkwonTheme theme) {
|
||||
// this.theme = theme;
|
||||
// return this;
|
||||
// }
|
||||
|
||||
@NonNull
|
||||
public Builder asyncDrawableLoader(@NonNull AsyncDrawable.Loader asyncDrawableLoader) {
|
||||
@ -263,11 +260,9 @@ public class MarkwonConfiguration {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MarkwonConfiguration build() {
|
||||
public MarkwonConfiguration build(@NonNull MarkwonTheme theme) {
|
||||
|
||||
if (theme == null) {
|
||||
theme = MarkwonTheme.create(context);
|
||||
}
|
||||
this.theme = theme;
|
||||
|
||||
if (asyncDrawableLoader == null) {
|
||||
asyncDrawableLoader = new AsyncDrawableLoaderNoOp();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ru.noties.markwon;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
@ -42,7 +43,26 @@ class MarkwonImpl extends Markwon2 {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public CharSequence markdown(@NonNull String input) {
|
||||
public CharSequence toMarkdown(@NonNull String input) {
|
||||
return render(parse(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarkdown(@NonNull TextView textView, @NonNull String markdown) {
|
||||
setParsedMarkdown(textView, toMarkdown(markdown));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
|
||||
for (MarkwonPlugin plugin : plugins) {
|
||||
plugin.beforeSetText(textView, markdown);
|
||||
}
|
||||
|
||||
textView.setText(markdown);
|
||||
|
||||
for (MarkwonPlugin plugin : plugins) {
|
||||
plugin.afterSetText(textView, markdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public interface MarkwonPlugin {
|
||||
@NonNull
|
||||
String processMarkdown(@NonNull String markdown);
|
||||
|
||||
void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder);
|
||||
void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown);
|
||||
|
||||
void afterSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder);
|
||||
void afterSetText(@NonNull TextView textView, @NonNull CharSequence markdown);
|
||||
}
|
||||
|
@ -20,14 +20,17 @@ public interface MarkwonVisitor extends Visitor {
|
||||
<N extends Node> Builder on(@NonNull Class<N> node, @NonNull NodeVisitor<N> nodeVisitor);
|
||||
|
||||
@NonNull
|
||||
MarkwonVisitor build(@NonNull MarkwonTheme theme, @NonNull MarkwonConfiguration configuration);
|
||||
MarkwonVisitor build(@NonNull MarkwonConfiguration configuration);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
MarkwonConfiguration configuration();
|
||||
|
||||
@NonNull
|
||||
MarkwonTheme theme();
|
||||
|
||||
@NonNull
|
||||
MarkwonConfiguration configuration();
|
||||
SpannableFactory factory();
|
||||
|
||||
@NonNull
|
||||
SpannableBuilder builder();
|
||||
|
@ -37,19 +37,21 @@ class MarkwonVisitorImpl implements MarkwonVisitor {
|
||||
|
||||
private final Map<Class<? extends Node>, NodeVisitor<? extends Node>> nodes;
|
||||
|
||||
private final MarkwonTheme theme;
|
||||
private final MarkwonConfiguration configuration;
|
||||
private final MarkwonTheme theme;
|
||||
private final SpannableFactory factory;
|
||||
|
||||
private final SpannableBuilder builder = new SpannableBuilder();
|
||||
|
||||
private int blockQuoteIndent;
|
||||
private int listLevel;
|
||||
|
||||
private MarkwonVisitorImpl(
|
||||
@NonNull MarkwonTheme theme,
|
||||
@NonNull MarkwonConfiguration configuration,
|
||||
@NonNull Map<Class<? extends Node>, NodeVisitor<? extends Node>> nodes) {
|
||||
this.theme = theme;
|
||||
this.configuration = configuration;
|
||||
this.theme = configuration.theme();
|
||||
this.factory = configuration.factory();
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
@ -173,6 +175,12 @@ class MarkwonVisitorImpl implements MarkwonVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MarkwonConfiguration configuration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MarkwonTheme theme() {
|
||||
@ -181,8 +189,8 @@ class MarkwonVisitorImpl implements MarkwonVisitor {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MarkwonConfiguration configuration() {
|
||||
return configuration;
|
||||
public SpannableFactory factory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -280,9 +288,8 @@ class MarkwonVisitorImpl implements MarkwonVisitor {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MarkwonVisitor build(@NonNull MarkwonTheme theme, @NonNull MarkwonConfiguration configuration) {
|
||||
public MarkwonVisitor build(@NonNull MarkwonConfiguration configuration) {
|
||||
return new MarkwonVisitorImpl(
|
||||
theme,
|
||||
configuration,
|
||||
Collections.unmodifiableMap(nodes));
|
||||
}
|
||||
|
@ -9,17 +9,24 @@ import org.commonmark.node.BulletList;
|
||||
import org.commonmark.node.Code;
|
||||
import org.commonmark.node.Emphasis;
|
||||
import org.commonmark.node.FencedCodeBlock;
|
||||
import org.commonmark.node.HardLineBreak;
|
||||
import org.commonmark.node.Heading;
|
||||
import org.commonmark.node.Image;
|
||||
import org.commonmark.node.IndentedCodeBlock;
|
||||
import org.commonmark.node.Link;
|
||||
import org.commonmark.node.ListBlock;
|
||||
import org.commonmark.node.ListItem;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.node.OrderedList;
|
||||
import org.commonmark.node.Paragraph;
|
||||
import org.commonmark.node.SoftLineBreak;
|
||||
import org.commonmark.node.StrongEmphasis;
|
||||
import org.commonmark.node.Text;
|
||||
import org.commonmark.node.ThematicBreak;
|
||||
|
||||
import ru.noties.markwon.AbstractMarkwonPlugin;
|
||||
import ru.noties.markwon.MarkwonConfiguration;
|
||||
import ru.noties.markwon.MarkwonVisitor;
|
||||
import ru.noties.markwon.SpannableBuilder;
|
||||
import ru.noties.markwon.spans.OrderedListItemSpan;
|
||||
|
||||
public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
@ -30,6 +37,25 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
|
||||
// todo: softBreak adds new line should be here (or maybe removed even?)
|
||||
|
||||
// todo: add a simple HTML handler
|
||||
// todo: configure primitive images (without okhttp -> just HttpUrlConnection and simple types (static, data)
|
||||
|
||||
@NonNull
|
||||
public static CorePlugin create() {
|
||||
return create(false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static CorePlugin create(boolean softBreakAddsNewLine) {
|
||||
return new CorePlugin(softBreakAddsNewLine);
|
||||
}
|
||||
|
||||
private final boolean softBreakAddsNewLine;
|
||||
|
||||
protected CorePlugin(boolean softBreakAddsNewLine) {
|
||||
this.softBreakAddsNewLine = softBreakAddsNewLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
|
||||
text(builder);
|
||||
@ -43,11 +69,17 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
orderedList(builder);
|
||||
listItem(builder);
|
||||
thematicBreak(builder);
|
||||
heading(builder);
|
||||
softLineBreak(builder);
|
||||
hardLineBreak(builder);
|
||||
paragraph(builder);
|
||||
image(builder);
|
||||
link(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) {
|
||||
OrderedListItemSpan.measure(textView, builder);
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
OrderedListItemSpan.measure(textView, markdown);
|
||||
}
|
||||
|
||||
protected void text(@NonNull MarkwonVisitor.Builder builder) {
|
||||
@ -65,7 +97,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull StrongEmphasis strongEmphasis) {
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(strongEmphasis);
|
||||
visitor.setSpans(length, visitor.configuration().factory().strongEmphasis());
|
||||
visitor.setSpans(length, visitor.factory().strongEmphasis());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -76,7 +108,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Emphasis emphasis) {
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(emphasis);
|
||||
visitor.setSpans(length, visitor.configuration().factory().emphasis());
|
||||
visitor.setSpans(length, visitor.factory().emphasis());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -95,7 +127,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
final int length = visitor.length();
|
||||
visitor.incrementBlockQuoteIndent();
|
||||
visitor.visitChildren(blockQuote);
|
||||
visitor.setSpans(length, visitor.configuration().factory().blockQuote(visitor.theme()));
|
||||
visitor.setSpans(length, visitor.factory().blockQuote(visitor.theme()));
|
||||
visitor.decrementBlockQuoteIndent();
|
||||
|
||||
if (visitor.hasNext(blockQuote)) {
|
||||
@ -122,7 +154,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
.append(code.getLiteral())
|
||||
.append('\u00a0');
|
||||
|
||||
visitor.setSpans(length, visitor.configuration().factory().code(visitor.theme(), false));
|
||||
visitor.setSpans(length, visitor.factory().code(visitor.theme(), false));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -163,7 +195,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
|
||||
visitor.builder().append('\u00a0');
|
||||
|
||||
visitor.setSpans(length, visitor.configuration().factory().code(visitor.theme(), true));
|
||||
visitor.setSpans(length, visitor.factory().code(visitor.theme(), true));
|
||||
|
||||
if (visitor.hasNext(node)) {
|
||||
visitor.ensureNewLine();
|
||||
@ -220,7 +252,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
final int start = ((OrderedList) parent).getStartNumber();
|
||||
|
||||
visitor.visitChildren(listItem);
|
||||
visitor.setSpans(length, visitor.configuration().factory().orderedListItem(visitor.theme(), start));
|
||||
visitor.setSpans(length, visitor.factory().orderedListItem(visitor.theme(), start));
|
||||
|
||||
|
||||
// after we have visited the children increment start number
|
||||
@ -230,7 +262,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
} else {
|
||||
|
||||
visitor.visitChildren(listItem);
|
||||
visitor.setSpans(length, visitor.configuration().factory().bulletListItem(visitor.theme(), visitor.listLevel() - 1));
|
||||
visitor.setSpans(length, visitor.factory().bulletListItem(visitor.theme(), visitor.listLevel() - 1));
|
||||
|
||||
}
|
||||
|
||||
@ -256,7 +288,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
// without space it won't render
|
||||
visitor.builder().append('\u00a0');
|
||||
|
||||
visitor.setSpans(length, visitor.configuration().factory().thematicBreak(visitor.theme()));
|
||||
visitor.setSpans(length, visitor.factory().thematicBreak(visitor.theme()));
|
||||
|
||||
if (visitor.hasNext(thematicBreak)) {
|
||||
visitor.ensureNewLine();
|
||||
@ -265,4 +297,132 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void heading(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(Heading.class, new MarkwonVisitor.NodeVisitor<Heading>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Heading heading) {
|
||||
|
||||
visitor.ensureNewLine();
|
||||
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(heading);
|
||||
visitor.setSpans(length, visitor.factory().heading(visitor.theme(), heading.getLevel()));
|
||||
|
||||
if (visitor.hasNext(heading)) {
|
||||
visitor.ensureNewLine();
|
||||
visitor.forceNewLine();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void softLineBreak(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(SoftLineBreak.class, new MarkwonVisitor.NodeVisitor<SoftLineBreak>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull SoftLineBreak softLineBreak) {
|
||||
if (softBreakAddsNewLine) {
|
||||
visitor.ensureNewLine();
|
||||
} else {
|
||||
visitor.builder().append(' ');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void hardLineBreak(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(HardLineBreak.class, new MarkwonVisitor.NodeVisitor<HardLineBreak>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull HardLineBreak hardLineBreak) {
|
||||
visitor.ensureNewLine();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void paragraph(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(Paragraph.class, new MarkwonVisitor.NodeVisitor<Paragraph>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Paragraph paragraph) {
|
||||
|
||||
final boolean inTightList = isInTightList(paragraph);
|
||||
|
||||
if (!inTightList) {
|
||||
visitor.ensureNewLine();
|
||||
}
|
||||
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(paragraph);
|
||||
|
||||
// @since 1.1.1 apply paragraph span
|
||||
visitor.setSpans(length, visitor.factory().paragraph(inTightList));
|
||||
|
||||
if (!inTightList && visitor.hasNext(paragraph)) {
|
||||
visitor.ensureNewLine();
|
||||
if (visitor.blockQuoteIndent() == 0) {
|
||||
visitor.forceNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void image(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(Image.class, new MarkwonVisitor.NodeVisitor<Image>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Image image) {
|
||||
|
||||
final int length = visitor.length();
|
||||
|
||||
visitor.visitChildren(image);
|
||||
|
||||
// we must check if anything _was_ added, as we need at least one char to render
|
||||
if (length == visitor.length()) {
|
||||
visitor.builder().append('\uFFFC');
|
||||
}
|
||||
|
||||
final MarkwonConfiguration configuration = visitor.configuration();
|
||||
|
||||
final Node parent = image.getParent();
|
||||
final boolean link = parent instanceof Link;
|
||||
final String destination = configuration
|
||||
.urlProcessor()
|
||||
.process(image.getDestination());
|
||||
|
||||
final Object spans = visitor.factory().image(
|
||||
visitor.theme(),
|
||||
destination,
|
||||
configuration.asyncDrawableLoader(),
|
||||
configuration.imageSizeResolver(),
|
||||
null,
|
||||
link);
|
||||
|
||||
visitor.setSpans(length, spans);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void link(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(Link.class, new MarkwonVisitor.NodeVisitor<Link>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Link link) {
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(link);
|
||||
final MarkwonConfiguration configuration = visitor.configuration();
|
||||
final String destination = configuration.urlProcessor().process(link.getDestination());
|
||||
visitor.setSpans(length, visitor.factory().link(visitor.theme(), destination, configuration.linkResolver()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isInTightList(@NonNull Paragraph paragraph) {
|
||||
final Node parent = paragraph.getParent();
|
||||
if (parent != null) {
|
||||
final Node gramps = parent.getParent();
|
||||
if (gramps instanceof ListBlock) {
|
||||
ListBlock list = (ListBlock) gramps;
|
||||
return list.isTight();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ public class OrderedListItemSpan implements LeadingMarginSpan {
|
||||
* NB, this method must be called <em>before</em> setting text to a TextView (`TextView#setText`
|
||||
* internally can trigger new Layout creation which will ask for leading margins right away)
|
||||
*
|
||||
* @param textView to which markdown will be applied
|
||||
* @param text parsed markdown to process
|
||||
* @param textView to which toMarkdown will be applied
|
||||
* @param text parsed toMarkdown to process
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public static void measure(@NonNull TextView textView, @NonNull CharSequence text) {
|
||||
|
@ -4,6 +4,7 @@ import android.text.Spanned;
|
||||
|
||||
public abstract class LeadingMarginUtils {
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public static boolean selfStart(int start, CharSequence text, Object span) {
|
||||
return text instanceof Spanned && ((Spanned) text).getSpanStart(span) == start;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class MainActivity extends Activity {
|
||||
|
||||
final SpannableBuilder builder = new SpannableBuilder();
|
||||
|
||||
// please note that here I am passing `0` as fallback it means that if markdown references
|
||||
// please note that here I am passing `0` as fallback it means that if toMarkdown references
|
||||
// unknown icon, it will try to load fallback one and will fail with ResourceNotFound. It's
|
||||
// better to provide a valid fallback option
|
||||
final IconSpanProvider spanProvider = IconSpanProvider.create(this, 0);
|
||||
@ -59,7 +59,7 @@ public class MainActivity extends Activity {
|
||||
.headingTextSizeMultipliers(textSizeMultipliers)
|
||||
.build())
|
||||
.build();
|
||||
// create an instance of visitor to process parsed markdown
|
||||
// create an instance of visitor to process parsed toMarkdown
|
||||
final IconVisitor visitor = new IconVisitor(
|
||||
configuration,
|
||||
builder,
|
||||
|
Loading…
x
Reference in New Issue
Block a user