flexmark-java
flexmark-java copied to clipboard
Support expand and collapsible feature for the code block
Is your feature request related to a problem? Please describe. We are trying to provide a feature that user can expand and collapse the code block as similar here https://gist.github.com/pierrejoubert73/902cc94d79424356a8d20be2b382e1ab#a-collapsible-section-containing-code
Describe the solution you'd like https://gist.github.com/pierrejoubert73/902cc94d79424356a8d20be2b382e1ab#a-collapsible-section-containing-code
Custom renderer code will do that:
import com.vladsch.flexmark.ast.FencedCodeBlock;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.html.HtmlRendererOptions;
import com.vladsch.flexmark.html.HtmlWriter;
import com.vladsch.flexmark.html.renderer.NodeRenderer;
import com.vladsch.flexmark.html.renderer.NodeRendererContext;
import com.vladsch.flexmark.html.renderer.NodeRendererFactory;
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.MutableDataHolder;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class Issue479 {
static class SampleExtension implements HtmlRenderer.HtmlRendererExtension {
@Override
public void rendererOptions(@NotNull MutableDataHolder options) {
// add any configuration settings to options you want to apply to everything, here
}
@Override
public void extend(@NotNull HtmlRenderer.Builder htmlRendererBuilder, @NotNull String rendererType) {
htmlRendererBuilder.nodeRendererFactory(new SampleNodeRenderer.Factory());
}
static SampleExtension create() {
return new SampleExtension();
}
}
static class SampleNodeRenderer implements NodeRenderer {
public SampleNodeRenderer(DataHolder options) {
}
@Override
public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
return new HashSet<>(Arrays.asList(
new NodeRenderingHandler<>(FencedCodeBlock.class, this::render)
));
}
private void render(FencedCodeBlock node, NodeRendererContext context, HtmlWriter html) {
html.tag("details", true, true, () -> {
html.tag("summary", true, true, () -> {
BasedSequence info = node.getInfo();
HtmlRendererOptions htmlOptions = context.getHtmlOptions();
if (info.isNotNull() && !info.isBlank()) {
String language = node.getInfoDelimitedByAny(htmlOptions.languageDelimiterSet).unescape();
html.append(language).append(" ");
}
html.append("(Click to expand.)");
});
context.delegateRender();
});
}
public static class Factory implements NodeRendererFactory {
@NotNull
@Override
public NodeRenderer apply(@NotNull DataHolder options) {
return new SampleNodeRenderer(options);
}
}
}
private static final DataHolder OPTIONS = new MutableDataSet().set(Parser.EXTENSIONS,
Arrays.asList(SampleExtension.create()));
;
public static Parser PARSER = Parser.builder(OPTIONS).build();
public static HtmlRenderer htmlRenderer = HtmlRenderer.builder(OPTIONS).build();
public static String getHtml(String markdownString) {
return htmlRenderer.render(PARSER.parse(markdownString));
}
public static void main(String[] args) {
String failing =
"" +
"```java\n" +
"public static void main(String[] args) {\n" +
" String failing =\n" +
" \"\" +\n" +
" ```java\n" +
" \"\\n\n" +
"\n" +
" System.out.println(\"```markdown\");\n" +
" System.out.println(failing);\n" +
" System.out.println(\"```\");\n" +
" System.out.println(\"```html\");\n" +
" System.out.println(Issue479.getHtml(failing));\n" +
" System.out.println(\"```\");\n" +
"}\n" +
"```\n" +
"";
System.out.println("```markdown");
System.out.println(failing);
System.out.println("```");
System.out.println("```html");
System.out.println(Issue479.getHtml(failing));
System.out.println("```");
}
}
Results in output:
```java
public static void main(String[] args) {
String failing =
"" +
```java
"\n
System.out.println("```markdown");
System.out.println(failing);
System.out.println("```");
System.out.println("```html");
System.out.println(Issue479.getHtml(failing));
System.out.println("```");
}
```
<details>
<summary>
java (Click to expand.)
</summary>
<pre><code class="language-java">public static void main(String[] args) {
String failing =
"" +
```java
"\n
System.out.println("```markdown");
System.out.println(failing);
System.out.println("```");
System.out.println("```html");
System.out.println(Issue479.getHtml(failing));
System.out.println("```");
}
</code></pre>
</details>
Renders as:
java (Click to expand.)
public static void main(String[] args) {
String failing =
"" +
```java
"\n
System.out.println("```markdown");
System.out.println(failing);
System.out.println("```");
System.out.println("```html");
System.out.println(Issue479.getHtml(failing));
System.out.println("```");
}