/** * @see #setMarkdown(TextView, SpannableConfiguration, String) * @since 1.0.0 */ public static void setMarkdown(@NonNull TextView view, @NonNull String markdown) { setMarkdown(view, SpannableConfiguration.create(view.getContext()), markdown); }
/** * Parses submitted raw markdown, converts it to CharSequence (with Spannables) * and applies it to view * * @param view {@link TextView} to set markdown into * @param configuration a {@link SpannableConfiguration} instance * @param markdown raw markdown String (for example: {@code `**Hello**`}) * @see #markdown(SpannableConfiguration, String) * @see #setText(TextView, CharSequence) * @see SpannableConfiguration * @since 1.0.0 */ public static void setMarkdown( @NonNull TextView view, @NonNull SpannableConfiguration configuration, @NonNull String markdown ) { setText(view, markdown(configuration, markdown)); }
/** * Helper method to apply parsed markdown 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 movementMethod an implementation if MovementMethod or null * @see #scheduleDrawables(TextView) * @see #scheduleTableRows(TextView) * @since 1.0.6 */ public static void setText(@NonNull TextView view, CharSequence text, @Nullable MovementMethod movementMethod) { unscheduleDrawables(view); 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 // 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); // update movement method (for links to be clickable) view.setMovementMethod(movementMethod); view.setText(text); // schedule drawables (dynamic drawables that can change bounds/animate will be correctly updated) scheduleDrawables(view); scheduleTableRows(view); }
/** * Returns parsed markdown with default {@link SpannableConfiguration} obtained from {@link Context} * * @param context {@link Context} * @param markdown raw markdown * @return parsed markdown * @since 1.0.0 */ @NonNull public static CharSequence markdown(@NonNull Context context, @NonNull String markdown) { final SpannableConfiguration configuration = SpannableConfiguration.create(context); return markdown(configuration, markdown); }
/** * Helper method to apply parsed markdown. * <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 * @see #setText(TextView, CharSequence, MovementMethod) * @since 1.0.0 */ public static void setText(@NonNull TextView view, CharSequence text) { setText(view, text, LinkMovementMethod.getInstance()); }
/** * Returns parsed markdown with provided {@link SpannableConfiguration} * * @param configuration a {@link SpannableConfiguration} * @param markdown raw markdown * @return parsed markdown * @see SpannableConfiguration * @since 1.0.0 */ @NonNull public static CharSequence markdown(@NonNull SpannableConfiguration configuration, @NonNull String markdown) { final Parser parser = createParser(); final Node node = parser.parse(markdown); final SpannableRenderer renderer = new SpannableRenderer(); return renderer.render(configuration, node); }
final CharSequence text = Markwon.markdown(configuration, markdown);
node.accept(visitor); Markwon.setText(textView, builder.text());
@Test public void test() { final TestData data = TestDataReader.readTest(file); final SpannableConfiguration configuration = configuration(data.config()); final SpannableBuilder builder = new SpannableBuilder(); final SpannableMarkdownVisitor visitor = new SpannableMarkdownVisitor(configuration, builder); final Node node = Markwon.createParser().parse(data.input()); node.accept(visitor); final SpannableStringBuilder stringBuilder = builder.spannableStringBuilder(); final TestValidator validator = TestValidator.create(file); int index = 0; for (TestNode testNode : data.output()) { index = validator.validate(stringBuilder, index, testNode); } // assert that the whole thing is processed assertEquals("`" + stringBuilder + "`", stringBuilder.length(), index); final Object[] spans = stringBuilder.getSpans(0, stringBuilder.length(), Object.class); final int length = spans != null ? spans.length : 0; assertEquals(Arrays.toString(spans), validator.processedSpanNodesCount(), length); }
@Override public void setMarkdown(@Nullable SpannableConfiguration configuration, @Nullable String markdown) { this.markdown = markdown; if (configuration == null) { if (this.configuration == null) { if (provider != null) { this.configuration = provider.provide(textView.getContext()); } else { this.configuration = SpannableConfiguration.create(textView.getContext()); } } configuration = this.configuration; } Markwon.setMarkdown(textView, configuration, markdown); }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_faq); ButterKnife.bind(this, this); try (InputStream inputStream = getResources().openRawResource(R.raw.faq)) { String markdown = IOUtils.toString(inputStream, StandardCharsets.UTF_8); Markwon.setMarkdown(faqText, markdown); } catch (IOException e) { Timber.e(e); } } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_changelog); ButterKnife.bind(this, this); try (InputStream inputStream = getResources().openRawResource(R.raw.changelog)) { String markdown = IOUtils.toString(inputStream, StandardCharsets.UTF_8); Markwon.setMarkdown(changelogText, markdown); } catch (IOException e) { Timber.e(e); } } }