flexmark-java icon indicating copy to clipboard operation
flexmark-java copied to clipboard

Support expand and collapsible feature for the code block

Open rampatina opened this issue 4 years ago • 1 comments

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

rampatina avatar Oct 04 '21 07:10 rampatina

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 =
            &quot;&quot; +
                    ```java
                    &quot;\n

    System.out.println(&quot;```markdown&quot;);
    System.out.println(failing);
    System.out.println(&quot;```&quot;);
    System.out.println(&quot;```html&quot;);
    System.out.println(Issue479.getHtml(failing));
    System.out.println(&quot;```&quot;);
}
</code></pre>
</details>

Renders as:

java (Click to expand.)
public static void main(String[] args) {
    String failing =
            "" +
                    ```java
                    "\n
System.out.println(&quot;```markdown&quot;);
System.out.println(failing);
System.out.println(&quot;```&quot;);
System.out.println(&quot;```html&quot;);
System.out.println(Issue479.getHtml(failing));
System.out.println(&quot;```&quot;);

}

vsch avatar Jan 25 '22 00:01 vsch