Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions flexmark-ext-docusaurus-admonition/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-java</artifactId>
<version>0.64.8</version>
</parent>

<artifactId>flexmark-ext-docusaurus-admonition</artifactId>
<name>flexmark-java extension for Docusaurus admonition syntax</name>
<description>flexmark-java extension for docusaurus admonition syntax</description>

<dependencies>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-util</artifactId>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark</artifactId>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-test-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-tables</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-core-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

import com.vladsch.flexmark.util.ast.Block;
import com.vladsch.flexmark.util.ast.BlockContent;
import com.vladsch.flexmark.util.sequence.BasedSequence;

class DocusaurusAdmonitionBlock extends Block {
private BasedSequence openingMarker = BasedSequence.NULL;
private BasedSequence type = BasedSequence.NULL;
private BasedSequence closingMarker = BasedSequence.NULL;
private final BlockContent content = new BlockContent();

public DocusaurusAdmonitionBlock() {
}

@Override
public BasedSequence[] getSegments() {
return new BasedSequence[]{openingMarker, type, closingMarker};
}

public BasedSequence getOpeningMarker() {
return this.openingMarker;
}

public BasedSequence getType() {
return this.type;
}

public BasedSequence getClosingMarker() {
return this.closingMarker;
}

public BlockContent getContent() {
return this.content;
}

public void setOpeningMarker(BasedSequence openingMarker) {
this.openingMarker = openingMarker;
}

public void setType(BasedSequence type) {
this.type = type;
}

public void setClosingMarker(BasedSequence closingMarker) {
this.closingMarker = closingMarker;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

import com.vladsch.flexmark.parser.block.*;
import com.vladsch.flexmark.util.ast.Block;
import com.vladsch.flexmark.util.ast.BlockContent;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import org.jetbrains.annotations.NotNull;

import java.util.Set;

class DocusaurusAdmonitionBlockParser extends AbstractBlockParser {
private final DocusaurusAdmonitionBlock block = new DocusaurusAdmonitionBlock();
private BlockContent content = new BlockContent();
private boolean hadClose = false;

private final String closingLine;

public DocusaurusAdmonitionBlockParser(BasedSequence openingMarker, BasedSequence type, int nestingLevel) {
block.setOpeningMarker(openingMarker);
block.setType(type);
closingLine = ":".repeat(nestingLevel);
}

@Override
public Block getBlock() {
return block;
}

@Override
public BlockContinue tryContinue(ParserState state) {

if (hadClose) {
return BlockContinue.none();
}

BasedSequence line = state.getLine();

boolean isClosingLine = line.matches(closingLine);

if (isClosingLine) {
block.setClosingMarker(line);
hadClose = true;
return BlockContinue.atIndex(state.getLineEndIndex());
}

return BlockContinue.atIndex(state.getIndex());
}

@Override
public boolean isContainer() {
return true; // can contain other blocks
}

@Override
public boolean canContain(ParserState state, BlockParser blockParser, Block block) {
return true; // can contain anything
}

@Override
public void addLine(ParserState state, BasedSequence line) {
content.add(line, state.getIndent());

}

@Override
public void closeBlock(ParserState state) {
block.setContent(content);
block.setCharsFromContent();

content = null;
}

public static class Factory implements CustomBlockParserFactory {
@Override
public @NotNull BlockParserFactory apply(@NotNull DataHolder options) {
return new BlockFactory(options);
}

@Override
public Set<Class<?>> getAfterDependents() {
return null;
}

@Override
public Set<Class<?>> getBeforeDependents() {
return null;
}

@Override
public boolean affectsGlobalScope() {
return false;
}
}

private static class BlockFactory extends AbstractBlockParserFactory {
BlockFactory(DataHolder options) {
super(options);
}

@Override
public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) {
BasedSequence line = state.getLine();
if (line.startsWith(":::")) {
int colons = 0;
while (colons < line.length() && line.charAt(colons) == ':') {
colons++;
}
BasedSequence type = line.subSequence(colons).trim();
if (!type.isEmpty() && !type.toString().contains(" ")) {
return BlockStart.of(new DocusaurusAdmonitionBlockParser(line.subSequence(0, colons), type, colons))
.atIndex(line.length());
}
}
return BlockStart.none();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataHolder;
import org.jetbrains.annotations.NotNull;

public class DocusaurusAdmonitionExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension {

public static DocusaurusAdmonitionExtension create() {
return new DocusaurusAdmonitionExtension();
}

@Override
public void extend(Parser.Builder parserBuilder) {
parserBuilder.customBlockParserFactory(new DocusaurusAdmonitionBlockParser.Factory());
}

@Override
public void extend(HtmlRenderer.@NotNull Builder rendererBuilder, String rendererType) {
if (rendererType.equals("HTML")) {
rendererBuilder.nodeRendererFactory(new DocusaurusAdmonitionNodeRenderer.Factory());
}
}

@Override
public void rendererOptions(@NotNull MutableDataHolder options) {
}

@Override
public void parserOptions(MutableDataHolder options) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

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.util.data.DataHolder;
import org.jetbrains.annotations.NotNull;

import java.util.HashSet;
import java.util.Set;

class DocusaurusAdmonitionNodeRenderer implements NodeRenderer {

@Override
public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
Set<NodeRenderingHandler<?>> set = new HashSet<>();
set.add(new NodeRenderingHandler<>(DocusaurusAdmonitionBlock.class, this::render));
return set;
}

private void render(DocusaurusAdmonitionBlock node, NodeRendererContext context, HtmlWriter html) {

String type = node.getType().toString();

html.attr("class", "docusaurus-admonition docusaurus-admonition-" + type);
html.withAttr().tag("div");

context.renderChildren(node);

html.tag("/div");
}

public static class Factory implements NodeRendererFactory {
@Override
public @NotNull NodeRenderer apply(@NotNull DataHolder options) {
return new DocusaurusAdmonitionNodeRenderer();
}
}
}
35 changes: 35 additions & 0 deletions flexmark-ext-docusaurus-admonition/src/main/javadoc/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# flexmark-ext-docusaurus-admonition

Extension for [Docusaurus Admonitions](https://docusaurus.io/docs/markdown-features/admonitions).

This extension renders Docusaurus admonitions into following HTML:

```html
<div class="docusaurus-admonition docusaurus-admonition-type">
<!-- any legal markdown here -->
</div>
```

Please note that `-type` in class name is replaced with actual type of the admonition eg. `note`, `tip` etc.

Nested admonitions are supported.

Custom admonitions are supported by replacing `-type` in class with custom adminition type. It means that the following Markdown:

```md

:::my-custom-admonition
Text here.
:::

```

Will be rendered as:

```html
<div class="docusaurus-admonition docusaurus-admonition-my-custom-admonition">
<p>Text here.</p>
</div>
```

Admonitions' titles are not supported now.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Document;
import org.junit.Assert;
import org.junit.Test;

import java.util.Collections;

public class DocusaurusAdmonitionBlockHtmlRendererTest {

@Test
public void checkParsing() {
Parser parser = Parser.builder().extensions(Collections.singleton(DocusaurusAdmonitionExtension.create())).build();

Document document = parser.parse(":::info\nThis is info\n:::");
Assert.assertTrue(document.getFirstChild() instanceof DocusaurusAdmonitionBlock);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.vladsch.flexmark.ext.docusaurus.admonition;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;

public class DocusaurusAdmonitionBlockParserTest {

@Test
public void checkParsing() {
MutableDataSet options = new MutableDataSet();
options.set(Parser.EXTENSIONS, List.of(
DocusaurusAdmonitionExtension.create()
));

Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build();

String markdownInput = ":::info\nThis is info\n:::";

// Act
String result = renderer.render(parser.parse(markdownInput));

// Assert
String expectedHtml = "<div class=\"docusaurus-admonition docusaurus-admonition-info\">\n<p>This is info</p>\n</div>\n";
Assert.assertEquals(expectedHtml, result);
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<module>flexmark-core-test</module>
<module>flexmark-ext-abbreviation</module>
<module>flexmark-ext-admonition</module>
<module>flexmark-ext-docusaurus-admonition</module>
<module>flexmark-ext-anchorlink</module>
<module>flexmark-ext-aside</module>
<module>flexmark-ext-attributes</module>
Expand Down