106 lines
3.5 KiB
Java
106 lines
3.5 KiB
Java
package io.noties.markwon.linkify;
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.style.URLSpan;
|
|
import android.text.util.Linkify;
|
|
|
|
import androidx.annotation.IntDef;
|
|
import androidx.annotation.NonNull;
|
|
|
|
import org.commonmark.node.Link;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
|
import io.noties.markwon.MarkwonVisitor;
|
|
import io.noties.markwon.RenderProps;
|
|
import io.noties.markwon.SpanFactory;
|
|
import io.noties.markwon.SpannableBuilder;
|
|
import io.noties.markwon.core.CorePlugin;
|
|
import io.noties.markwon.core.CoreProps;
|
|
|
|
public class LinkifyPlugin extends AbstractMarkwonPlugin {
|
|
|
|
@IntDef(flag = true, value = {
|
|
Linkify.EMAIL_ADDRESSES,
|
|
Linkify.PHONE_NUMBERS,
|
|
Linkify.WEB_URLS
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@interface LinkifyMask {
|
|
}
|
|
|
|
@NonNull
|
|
public static LinkifyPlugin create() {
|
|
return create(Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS | Linkify.WEB_URLS);
|
|
}
|
|
|
|
@NonNull
|
|
public static LinkifyPlugin create(@LinkifyMask int mask) {
|
|
return new LinkifyPlugin(mask);
|
|
}
|
|
|
|
private final int mask;
|
|
|
|
@SuppressWarnings("WeakerAccess")
|
|
LinkifyPlugin(@LinkifyMask int mask) {
|
|
this.mask = mask;
|
|
}
|
|
|
|
@Override
|
|
public void configure(@NonNull Registry registry) {
|
|
registry.require(CorePlugin.class, new Action<CorePlugin>() {
|
|
@Override
|
|
public void apply(@NonNull CorePlugin corePlugin) {
|
|
corePlugin.addOnTextAddedListener(new LinkifyTextAddedListener(mask));
|
|
}
|
|
});
|
|
}
|
|
|
|
private static class LinkifyTextAddedListener implements CorePlugin.OnTextAddedListener {
|
|
|
|
private final int mask;
|
|
|
|
LinkifyTextAddedListener(int mask) {
|
|
this.mask = mask;
|
|
}
|
|
|
|
@Override
|
|
public void onTextAdded(@NonNull MarkwonVisitor visitor, @NonNull String text, int start) {
|
|
|
|
// @since 4.2.0-SNAPSHOT obtain span factory for links
|
|
// we will be using the link that is used by markdown (instead of directly applying URLSpan)
|
|
final SpanFactory spanFactory = visitor.configuration().spansFactory().get(Link.class);
|
|
if (spanFactory == null) {
|
|
return;
|
|
}
|
|
|
|
// @since 4.2.0-SNAPSHOT we no longer re-use builder (thread safety achieved for
|
|
// render calls from different threads and ... better performance)
|
|
final SpannableStringBuilder builder = new SpannableStringBuilder(text);
|
|
|
|
if (Linkify.addLinks(builder, mask)) {
|
|
// target URL span specifically
|
|
final URLSpan[] spans = builder.getSpans(0, builder.length(), URLSpan.class);
|
|
if (spans != null
|
|
&& spans.length > 0) {
|
|
|
|
final RenderProps renderProps = visitor.renderProps();
|
|
final SpannableBuilder spannableBuilder = visitor.builder();
|
|
|
|
for (URLSpan span : spans) {
|
|
CoreProps.LINK_DESTINATION.set(renderProps, span.getURL());
|
|
SpannableBuilder.setSpans(
|
|
spannableBuilder,
|
|
spanFactory.getSpans(visitor.configuration(), renderProps),
|
|
start + builder.getSpanStart(span),
|
|
start + builder.getSpanEnd(span)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|