diff --git a/markwon-test-util/build.gradle b/markwon-test-util/build.gradle
deleted file mode 100644
index 3909ab27..00000000
--- a/markwon-test-util/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-apply plugin: 'java-library'
-
-sourceCompatibility = 1.7
-targetCompatibility = 1.7
-
-dependencies {
-
- api deps['support-annotations']
-
- deps['test'].with {
- implementation it['commons-io']
- }
-}
\ No newline at end of file
diff --git a/markwon-test-util/src/main/java/ru/noties/markwon/test/TestUtil.java b/markwon-test-util/src/main/java/ru/noties/markwon/test/TestUtil.java
deleted file mode 100644
index 2ce00e1f..00000000
--- a/markwon-test-util/src/main/java/ru/noties/markwon/test/TestUtil.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package ru.noties.markwon.test;
-
-import android.support.annotation.NonNull;
-
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-public abstract class TestUtil {
-
- @NonNull
- public static String read(@NonNull String path) {
- try {
- return IOUtils.resourceToString(path, StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- @NonNull
- public static String read(@NonNull Object who, @NonNull String path) {
- try {
- return IOUtils.resourceToString(path, StandardCharsets.UTF_8, who.getClass().getClassLoader());
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private TestUtil() {
- }
-}
diff --git a/markwon/build.gradle b/markwon/build.gradle
index 604519a2..8682d261 100644
--- a/markwon/build.gradle
+++ b/markwon/build.gradle
@@ -23,17 +23,12 @@ dependencies {
deps['test'].with {
testImplementation project(':markwon-test-span')
- testImplementation project(':markwon-test-util')
testImplementation it['junit']
testImplementation it['robolectric']
testImplementation it['mockito']
- // to remove after migration
testImplementation it['ix-java']
- testImplementation it['jackson-yaml']
- testImplementation it['jackson-databind']
- testImplementation it['gson']
testImplementation it['commons-io']
}
}
diff --git a/markwon/src/main/java/ru/noties/markwon/AbstractMarkwonPlugin.java b/markwon/src/main/java/ru/noties/markwon/AbstractMarkwonPlugin.java
index 28767521..d9849e5c 100644
--- a/markwon/src/main/java/ru/noties/markwon/AbstractMarkwonPlugin.java
+++ b/markwon/src/main/java/ru/noties/markwon/AbstractMarkwonPlugin.java
@@ -1,6 +1,7 @@
package ru.noties.markwon;
import android.support.annotation.NonNull;
+import android.text.Spanned;
import android.widget.TextView;
import org.commonmark.node.Node;
@@ -9,63 +10,107 @@ import org.commonmark.parser.Parser;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.image.AsyncDrawableLoader;
+/**
+ * Class that extends {@link MarkwonPlugin} with all methods implemented (empty body)
+ * for easier plugin implementation. Only required methods can be overriden
+ *
+ * @see MarkwonPlugin
+ * @since 3.0.0
+ */
public abstract class AbstractMarkwonPlugin implements MarkwonPlugin {
+
+ /**
+ * @inheritDoc
+ */
@Override
public void configureParser(@NonNull Parser.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void configureRenderProps(@NonNull RenderProps renderProps) {
}
+ /**
+ * @inheritDoc
+ */
@NonNull
@Override
public String processMarkdown(@NonNull String markdown) {
return markdown;
}
+ /**
+ * @inheritDoc
+ */
@Override
public void beforeRender(@NonNull Node node) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void afterRender(@NonNull Node node, @NonNull MarkwonVisitor visitor) {
}
+ /**
+ * @inheritDoc
+ */
@Override
- public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
+ public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
}
+ /**
+ * @inheritDoc
+ */
@Override
public void afterSetText(@NonNull TextView textView) {
diff --git a/markwon/src/main/java/ru/noties/markwon/Markwon.java b/markwon/src/main/java/ru/noties/markwon/Markwon.java
index 6c4e4bea..c5a9ea8c 100644
--- a/markwon/src/main/java/ru/noties/markwon/Markwon.java
+++ b/markwon/src/main/java/ru/noties/markwon/Markwon.java
@@ -7,9 +7,20 @@ import android.widget.TextView;
import org.commonmark.node.Node;
+/**
+ * Class to parse and render markdown. Since version 3.0.0 instance specific (previously consisted
+ * of static stateless methods). An instance of builder can be obtained via {@link #builder(Context)}
+ * method.
+ *
+ * @see #builder(Context)
+ * @see Builder
+ */
public abstract class Markwon {
/**
+ * Factory method to obtain an instance of {@link Builder}
+ *
+ * @see Builder
* @since 3.0.0
*/
@NonNull
@@ -17,6 +28,14 @@ public abstract class Markwon {
return new MarkwonBuilderImpl(context);
}
+ /**
+ * Method to simply parse markdown (without rendering)
+ *
+ * @param input markdown input to parse
+ * @return parsed via commonmark-java org.commonmark.node.Node
+ * @see #render(Node)
+ * @since 3.0.0
+ */
@NonNull
public abstract Node parse(@NonNull String input);
@@ -29,9 +48,14 @@ public abstract class Markwon {
public abstract void setMarkdown(@NonNull TextView textView, @NonNull String markdown);
- public abstract void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown);
+ public abstract void setParsedMarkdown(@NonNull TextView textView, @NonNull Spanned markdown);
/**
+ * Builder for {@link Markwon}.
+ *
+ * Please note that the order in which plugins are supplied is important as this order will be
+ * used through the whole usage of built Markwon instance
+ *
* @since 3.0.0
*/
public interface Builder {
diff --git a/markwon/src/main/java/ru/noties/markwon/MarkwonBuilderImpl.java b/markwon/src/main/java/ru/noties/markwon/MarkwonBuilderImpl.java
index 6098155a..1cf15c2c 100644
--- a/markwon/src/main/java/ru/noties/markwon/MarkwonBuilderImpl.java
+++ b/markwon/src/main/java/ru/noties/markwon/MarkwonBuilderImpl.java
@@ -80,7 +80,6 @@ class MarkwonBuilderImpl implements Markwon.Builder {
plugin.configureConfiguration(configurationBuilder);
plugin.configureVisitor(visitorBuilder);
plugin.configureSpansFactory(spanFactoryBuilder);
- plugin.configureRenderProps(renderProps);
}
final MarkwonConfiguration configuration = configurationBuilder.build(
diff --git a/markwon/src/main/java/ru/noties/markwon/MarkwonImpl.java b/markwon/src/main/java/ru/noties/markwon/MarkwonImpl.java
index 2114f050..8e2d8791 100644
--- a/markwon/src/main/java/ru/noties/markwon/MarkwonImpl.java
+++ b/markwon/src/main/java/ru/noties/markwon/MarkwonImpl.java
@@ -9,6 +9,9 @@ import org.commonmark.parser.Parser;
import java.util.List;
+/**
+ * @since 3.0.0
+ */
class MarkwonImpl extends Markwon {
private final TextView.BufferType bufferType;
@@ -31,6 +34,7 @@ class MarkwonImpl extends Markwon {
@Override
public Node parse(@NonNull String input) {
+ // make sure that all plugins are called `processMarkdown` before parsing
for (MarkwonPlugin plugin : plugins) {
input = plugin.processMarkdown(input);
}
@@ -42,7 +46,14 @@ class MarkwonImpl extends Markwon {
@Override
public Spanned render(@NonNull Node node) {
+ final RenderProps renderProps = visitor.renderProps();
+
for (MarkwonPlugin plugin : plugins) {
+
+ // let plugins apply render properties before rendering (as we will clear
+ // renderProps after rendering)
+ plugin.configureRenderProps(renderProps);
+
plugin.beforeRender(node);
}
@@ -52,6 +63,9 @@ class MarkwonImpl extends Markwon {
plugin.afterRender(node, visitor);
}
+ // clear render props after rending
+ renderProps.clearAll();
+
return visitor.builder().spannableStringBuilder();
}
@@ -67,7 +81,7 @@ class MarkwonImpl extends Markwon {
}
@Override
- public void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown) {
+ public void setParsedMarkdown(@NonNull TextView textView, @NonNull Spanned markdown) {
for (MarkwonPlugin plugin : plugins) {
plugin.beforeSetText(textView, markdown);
diff --git a/markwon/src/main/java/ru/noties/markwon/MarkwonPlugin.java b/markwon/src/main/java/ru/noties/markwon/MarkwonPlugin.java
index 910b044e..fd99b4dd 100644
--- a/markwon/src/main/java/ru/noties/markwon/MarkwonPlugin.java
+++ b/markwon/src/main/java/ru/noties/markwon/MarkwonPlugin.java
@@ -1,6 +1,7 @@
package ru.noties.markwon;
import android.support.annotation.NonNull;
+import android.text.Spanned;
import android.widget.TextView;
import org.commonmark.node.Node;
@@ -8,38 +9,137 @@ import org.commonmark.parser.Parser;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.image.AsyncDrawableLoader;
+import ru.noties.markwon.image.MediaDecoder;
+import ru.noties.markwon.image.SchemeHandler;
/**
+ * Class represents a plugin (extension) to Markwon to configure how parsing and rendering
+ * of markdown is carried on.
+ *
+ * @see AbstractMarkwonPlugin
+ * @see ru.noties.markwon.core.CorePlugin
+ * @see ru.noties.markwon.image.ImagesPlugin
* @since 3.0.0
*/
public interface MarkwonPlugin {
+ /**
+ * Method to configure org.commonmark.parser.Parser
(for example register custom
+ * extension, etc).
+ */
void configureParser(@NonNull Parser.Builder builder);
+ /**
+ * Modify {@link MarkwonTheme} that is used for rendering of markdown.
+ *
+ * @see MarkwonTheme
+ * @see MarkwonTheme.Builder
+ */
void configureTheme(@NonNull MarkwonTheme.Builder builder);
+ /**
+ * Configure image loading functionality. For example add new content-types
+ * {@link AsyncDrawableLoader.Builder#addMediaDecoder(String, MediaDecoder)}, a transport
+ * layer (network, file, etc) {@link AsyncDrawableLoader.Builder#addSchemeHandler(String, SchemeHandler)}
+ * or modify existing properties.
+ *
+ * @see AsyncDrawableLoader
+ * @see AsyncDrawableLoader.Builder
+ */
void configureImages(@NonNull AsyncDrawableLoader.Builder builder);
+ /**
+ * Configure {@link MarkwonConfiguration}
+ *
+ * @see MarkwonConfiguration
+ * @see MarkwonConfiguration.Builder
+ */
void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder);
+ /**
+ * Configure {@link MarkwonVisitor} to accept new node types or override already registered nodes.
+ *
+ * @see MarkwonVisitor
+ * @see MarkwonVisitor.Builder
+ */
void configureVisitor(@NonNull MarkwonVisitor.Builder builder);
+ /**
+ * Configure {@link MarkwonSpansFactory} to change what spans are used for certain node types.
+ *
+ * @see MarkwonSpansFactory
+ * @see MarkwonSpansFactory.Builder
+ */
void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder);
// can be used to configure own properties and use between plugins
+
+ /**
+ * A method to store some arbitrary data in {@link RenderProps}. Although it won\'t make
+ * much sense to use existing {@link Prop} keys for {@link SpanFactory}, it can be helpful
+ * to establish a communication channel between multiple plugins in decoupled way (provide
+ * some initial properties for example or indicate that certain plugin is registered).
+ *
+ * This method will be called before each rendering step (after rendering {@link RenderProps}
+ * will be cleared. This method won\'t be called during initialization stage.
+ *
+ * @see RenderProps
+ */
void configureRenderProps(@NonNull RenderProps renderProps);
+ /**
+ * Process input markdown and return new string to be used in parsing stage further.
+ * Can be described as pre-processing
of markdown String.
+ *
+ * @param markdown String to process
+ * @return processed markdown String
+ */
@NonNull
String processMarkdown(@NonNull String markdown);
+ /**
+ * This method will be called before rendering will occur thus making possible
+ * to post-process
parsed node (make changes for example).
+ *
+ * @param node root parsed org.commonmark.node.Node
+ */
void beforeRender(@NonNull Node node);
+ /**
+ * This method will be called after rendering (but before applying markdown to a
+ * TextView, if such action will happen). It can be used to clean some
+ * internal state, or trigger certain action. Please note that modifying node
won\'t
+ * have any effect as it has been already visited at this stage.
+ *
+ * @param node root parsed org.commonmark.node.Node
+ * @param visitor {@link MarkwonVisitor} instance used to render markdown
+ */
void afterRender(@NonNull Node node, @NonNull MarkwonVisitor visitor);
- void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown);
+ /**
+ * This method will be called before calling TextView#setText
.
+ *
+ * It can be useful to prepare a TextView for markdown. For example {@link ru.noties.markwon.image.ImagesPlugin}
+ * uses this method to unregister previously registered {@link ru.noties.markwon.image.AsyncDrawableSpan}
+ * (if there are such spans in this TextView at this point). Or {@link ru.noties.markwon.core.CorePlugin}
+ * which measures ordered list numbers
+ *
+ * @param textView TextView to which markdown
will be applied
+ * @param markdown Parsed markdown
+ */
+ void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown);
- // this method do not receive markdown like `beforeSetText` does because at this
- // point TextView already has markdown set and to manipulate spans one must
- // request them from TextView (getText())
+ /**
+ * This method will be called after markdown was applied.
+ *
+ * It can be useful to trigger certain action on spans/textView. For example {@link ru.noties.markwon.image.ImagesPlugin} + * uses this method to register {@link ru.noties.markwon.image.AsyncDrawableSpan} and start + * asynchronously loading images. + *
+ * Unlike {@link #beforeSetText(TextView, Spanned)} this method does not receive parsed markdown
+ * as at this point spans must be queried by calling
+ * Since version 3.0.0 this class should be considered as CoreTheme as it\'s
+ * information holds data for core features only. But based on this other components can still use it
+ * to display markdown consistently.
+ *
+ * Since version 3.0.0 this class should not be instantiated manually. Instead a {@link ru.noties.markwon.MarkwonPlugin}
+ * should be used: {@link ru.noties.markwon.MarkwonPlugin#configureTheme(Builder)}
+ *
+ * Since version 3.0.0 properties related to strike-through, tables and HTML
+ * are moved to specific plugins in independent artifacts
+ *
+ * @see CorePlugin
+ * @see ru.noties.markwon.MarkwonPlugin#configureTheme(Builder)
+ */
@SuppressWarnings("WeakerAccess")
public class MarkwonTheme {
@@ -41,12 +57,28 @@ public class MarkwonTheme {
* @see #builderWithDefaults(Context)
* @see #builder(MarkwonTheme)
* @since 1.0.0
+ * @deprecated 3.0.0
*/
@NonNull
+ @Deprecated
public static Builder builder() {
return new Builder();
}
+ /**
+ * Create an empty instance of {@link Builder} with no default values applied
+ *
+ * Since version 3.0.0 manual construction of {@link MarkwonTheme} is not required, instead a
+ * {@link ru.noties.markwon.MarkwonPlugin#configureTheme(Builder)} should be used in order
+ * to change certain theme properties
+ *
+ * @since 3.0.0
+ */
+ @NonNull
+ public static Builder builderNoDefaults() {
+ return new Builder();
+ }
+
/**
* Factory method to create a {@link Builder} instance and initialize it with values
* from supplied {@link MarkwonTheme}
@@ -549,6 +581,7 @@ public class MarkwonTheme {
* @return self
* @since 1.1.0
*/
+ @SuppressWarnings("UnusedReturnValue")
@NonNull
public Builder headingTextSizeMultipliers(@Size(6) @NonNull float[] headingTextSizeMultipliers) {
this.headingTextSizeMultipliers = headingTextSizeMultipliers;
diff --git a/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java b/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java
index 7e91f288..dc51504f 100644
--- a/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java
+++ b/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java
@@ -2,6 +2,7 @@ package ru.noties.markwon.image;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.text.Spanned;
import android.widget.TextView;
import org.commonmark.node.Image;
@@ -15,6 +16,7 @@ import ru.noties.markwon.MarkwonConfiguration;
import ru.noties.markwon.MarkwonSpansFactory;
import ru.noties.markwon.MarkwonVisitor;
import ru.noties.markwon.RenderProps;
+import ru.noties.markwon.SpanFactory;
import ru.noties.markwon.image.data.DataUriSchemeHandler;
import ru.noties.markwon.image.file.FileSchemeHandler;
import ru.noties.markwon.image.network.NetworkSchemeHandler;
@@ -68,6 +70,13 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
@Override
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Image image) {
+ // if there is no image spanFactory, ignore
+ final SpanFactory spanFactory = visitor.configuration().spansFactory().get(image);
+ if (spanFactory == null) {
+ visitor.visitChildren(image);
+ return;
+ }
+
final int length = visitor.length();
visitor.visitChildren(image);
@@ -86,22 +95,22 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
.urlProcessor()
.process(image.getDestination());
- final RenderProps context = visitor.renderProps();
+ final RenderProps props = visitor.renderProps();
// apply image properties
// Please note that we explicitly set IMAGE_SIZE to null as we do not clear
// properties after we applied span (we could though)
- ImageProps.DESTINATION.set(context, destination);
- ImageProps.REPLACEMENT_TEXT_IS_LINK.set(context, link);
- ImageProps.IMAGE_SIZE.set(context, null);
+ ImageProps.DESTINATION.set(props, destination);
+ ImageProps.REPLACEMENT_TEXT_IS_LINK.set(props, link);
+ ImageProps.IMAGE_SIZE.set(props, null);
- visitor.setSpansForNode(image, length);
+ visitor.setSpans(length, spanFactory.getSpans(configuration, props));
}
});
}
@Override
- public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
+ public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
AsyncDrawableScheduler.unschedule(textView);
}
diff --git a/markwon/src/test/java/ru/noties/markwon/core/suite/BaseSuiteTest.java b/markwon/src/test/java/ru/noties/markwon/core/suite/BaseSuiteTest.java
index f91f2f13..98734db7 100644
--- a/markwon/src/test/java/ru/noties/markwon/core/suite/BaseSuiteTest.java
+++ b/markwon/src/test/java/ru/noties/markwon/core/suite/BaseSuiteTest.java
@@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Spanned;
+import org.apache.commons.io.IOUtils;
import org.commonmark.node.BlockQuote;
import org.commonmark.node.Code;
import org.commonmark.node.Emphasis;
@@ -18,7 +19,8 @@ import org.commonmark.node.StrongEmphasis;
import org.commonmark.node.ThematicBreak;
import org.robolectric.RuntimeEnvironment;
-import java.util.Collections;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@@ -32,7 +34,6 @@ import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.CoreProps;
import ru.noties.markwon.test.TestSpan;
import ru.noties.markwon.test.TestSpanMatcher;
-import ru.noties.markwon.test.TestUtil;
import static ru.noties.markwon.test.TestSpan.args;
import static ru.noties.markwon.test.TestSpan.span;
@@ -62,7 +63,11 @@ abstract class BaseSuiteTest {
@NonNull
private String read(@NonNull String name) {
- return TestUtil.read(this, "tests/" + name);
+ try {
+ return IOUtils.resourceToString("tests/" + name, StandardCharsets.UTF_8, getClass().getClassLoader());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
@NonNull
@@ -160,12 +165,7 @@ abstract class BaseSuiteTest {
@Nullable
@Override
public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
- return span(name, extractArgs(props));
- }
-
- @NonNull
- MapTextView#getText#getSpans
.
+ *
+ * @param textView TextView to which markdown was applied
+ */
void afterSetText(@NonNull TextView textView);
}
diff --git a/markwon/src/main/java/ru/noties/markwon/MarkwonSpansFactory.java b/markwon/src/main/java/ru/noties/markwon/MarkwonSpansFactory.java
index 748ebd57..70545066 100644
--- a/markwon/src/main/java/ru/noties/markwon/MarkwonSpansFactory.java
+++ b/markwon/src/main/java/ru/noties/markwon/MarkwonSpansFactory.java
@@ -6,27 +6,46 @@ import android.support.annotation.Nullable;
import org.commonmark.node.Node;
/**
+ * Class that controls what spans are used for certain Nodes.
+ *
+ * @see SpanFactory
* @since 3.0.0
*/
public interface MarkwonSpansFactory {
+ /**
+ * Returns registered {@link SpanFactory} or null
if a factory for this node type
+ * is not registered. There is {@link #require(Class)} method that will throw an exception
+ * if required {@link SpanFactory} is not registered, thus making return type non-null
+ *
+ * @param node type of the node
+ * @return registered {@link SpanFactory} or null if it\'s not registered
+ * @see #require(Class)
+ */
@Nullable
- builder().length()
+ *
+ * @return current length of underlying {@link SpannableBuilder}
+ */
int length();
+ /**
+ * Sets spans
to underlying {@link SpannableBuilder} from start
+ * to {@link SpannableBuilder#length()}.
+ *
+ * @param start start position of spans
+ * @param spans to apply
+ */
void setSpans(int start, @Nullable Object spans);
- // will automatically obtain SpanFactory instance and use it, it no SpanFactory is registered,
- // will throw, if not desired use setSpansForNodeOptional
+ /**
+ * Helper method to obtain and apply spans for supplied Node. Internally queries {@link SpanFactory}
+ * for the node (via {@link MarkwonSpansFactory#require(Node)} thus throwing an exception
+ * if there is no {@link SpanFactory} registered for the node).
+ *
+ * @param node to retrieve {@link SpanFactory} for
+ * @param start start position for further {@link #setSpans(int, Object)} call
+ * @see #setSpansForNodeOptional(Node, int)
+ */
node
has a {@link SpanFactory} registered,
+ * then {@link #setSpansForNode(Node, int)} can be used. {@link #setSpansForNode(Node, int)} internally
+ * uses {@link MarkwonSpansFactory#require(Node)}. This method uses {@link MarkwonSpansFactory#get(Node)}.
+ *
+ * @see #setSpansForNode(Node, int)
+ */