diff --git a/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java b/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java
index 5a041574..2ac5cb96 100644
--- a/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java
+++ b/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java
@@ -49,7 +49,7 @@ public class MarkupTableColumn {
* Set column width ratio for this column.
* Limited support : Markdown does not support column width specifiers and will ignore {@code widthRatio}.
*
- * @param widthRatio width ratio integer value [0-100]. Accept relative width specifiers [0-9] for languages supporting it.
+ * @param widthRatio width ratio integer value [0-100]. Accept relative width specifiers (e.g.: 1, 2, 3, .. with Sum{i=0->nbCols}(widthRatio(i)) != 100).
* @return this builder
*/
public MarkupTableColumn withWidthRatio(Integer widthRatio) {
diff --git a/src/main/java/io/github/robwin/markup/builder/internal/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/internal/AbstractMarkupDocBuilder.java
index f39d47ad..2497248c 100644
--- a/src/main/java/io/github/robwin/markup/builder/internal/AbstractMarkupDocBuilder.java
+++ b/src/main/java/io/github/robwin/markup/builder/internal/AbstractMarkupDocBuilder.java
@@ -228,18 +228,31 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder {
return listing(replaceNewLines(text), null);
}
- protected void delimitedBlockText(Markup markup, String text) {
- if (markup != null)
- documentBuilder.append(markup).append(newLine);
+ protected void delimitedBlockText(Markup begin, String text, Markup end) {
+ Validate.notBlank(text, "text must not be null");
+ if (!StringUtils.isBlank(begin.toString()))
+ documentBuilder.append(begin).append(newLine);
documentBuilder.append(replaceNewLines(text)).append(newLine);
- if (markup != null)
- documentBuilder.append(markup).append(newLine);
+ if (!StringUtils.isBlank(end.toString()))
+ documentBuilder.append(end).append(newLine);
documentBuilder.append(newLine);
}
- protected void delimitedTextWithoutLineBreaks(Markup markup, String text) {
+ protected void delimitedTextWithoutLineBreaks(Markup begin, String text, Markup end) {
Validate.notBlank(text, "text must not be null");
- documentBuilder.append(markup).append(replaceNewLines(text)).append(markup);
+ if (!StringUtils.isBlank(begin.toString()))
+ documentBuilder.append(begin);
+ documentBuilder.append(replaceNewLines(text));
+ if (!StringUtils.isBlank(end.toString()))
+ documentBuilder.append(end);
+ }
+
+ protected void delimitedBlockText(Markup markup, String text) {
+ delimitedBlockText(markup, text, markup);
+ }
+
+ protected void delimitedTextWithoutLineBreaks(Markup markup, String text) {
+ delimitedTextWithoutLineBreaks(markup, text, markup);
}
protected void boldText(Markup markup, String text) {
@@ -255,7 +268,7 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder {
}
@Override
- public MarkupDocBuilder boldTextLine(String text) {
+ public MarkupDocBuilder boldTextLine(String text) {
return boldTextLine(text, LINE_BREAK_DEFAULT);
}
@@ -457,12 +470,12 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder {
logger.info("Markup document written to: {}", file);
}
}
-
- public String replaceNewLines(String content){
+
+ public String replaceNewLines(String content) {
return content.replaceAll(NEW_LINES, newLine);
}
- public String replaceNewLinesWithWhiteSpace(String content){
+ public String replaceNewLinesWithWhiteSpace(String content) {
return content.replaceAll(NEW_LINES, WHITESPACE);
}
diff --git a/src/main/java/io/github/robwin/markup/builder/internal/asciidoc/AsciiDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/internal/asciidoc/AsciiDocBuilder.java
index aa1d9928..4ba9e88b 100644
--- a/src/main/java/io/github/robwin/markup/builder/internal/asciidoc/AsciiDocBuilder.java
+++ b/src/main/java/io/github/robwin/markup/builder/internal/asciidoc/AsciiDocBuilder.java
@@ -92,7 +92,6 @@ public class AsciiDocBuilder extends AbstractMarkupDocBuilder {
delimitedBlockText(new Markup() {
public String toString() {
- assert (BLOCK_STYLE.containsKey(style));
return BLOCK_STYLE.get(style);
}
}, text);
diff --git a/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkup.java b/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkup.java
index 86cf0b34..5fbb9e4e 100644
--- a/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkup.java
+++ b/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkup.java
@@ -25,6 +25,13 @@ import io.github.robwin.markup.builder.internal.Markup;
* @author Robert Winkler
*/
public enum ConfluenceMarkup implements Markup {
+ TABLE_COLUMN_DELIMITER("|"),
+ TABLE_COLUMN_DELIMITER_ESCAPE("\\|"),
+ BOLD("*"),
+ ITALIC("_"),
+ LIST_ENTRY("* "),
+ ANCHOR_START("{anchor:"),
+ ANCHOR_END("}"),
FILE_EXTENSION("txt"),
SPACE_ESCAPE("_"),
LINE_BREAK("\\\\ ");
diff --git a/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkupBuilder.java b/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkupBuilder.java
index dce8c763..76c23e99 100644
--- a/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkupBuilder.java
+++ b/src/main/java/io/github/robwin/markup/builder/internal/confluenceMarkup/ConfluenceMarkupBuilder.java
@@ -23,18 +23,45 @@ import io.github.robwin.markup.builder.MarkupBlockStyle;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.markup.builder.MarkupTableColumn;
import io.github.robwin.markup.builder.internal.AbstractMarkupDocBuilder;
+import io.github.robwin.markup.builder.internal.Markup;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.io.Reader;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
-import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
private static final Pattern TITLE_PATTERN = Pattern.compile("^h([0-9])\\.\\s+(.*)$");
+ private static final String TITLE_FORMAT = "h%d. %s";
+
+ /**
+ * Associate macro name to block style.
+ * ending ':' means the macro supports title attribute.
+ * '>ADMONITION_BLOCK' means value should refer to {@link #ADMONITION_BLOCK_STYLE}.
+ */
+ private static final Map BLOCK_STYLE = new HashMap() {{
+ put(MarkupBlockStyle.EXAMPLE, ">ADMONITION_BLOCK");
+ put(MarkupBlockStyle.LISTING, "code:");
+ put(MarkupBlockStyle.LITERAL, "noformat");
+ put(MarkupBlockStyle.PASSTHROUGH, "html");
+ put(MarkupBlockStyle.SIDEBAR, ">ADMONITION_BLOCK");
+ }};
+
+ private static final Map ADMONITION_BLOCK_STYLE = new HashMap() {{
+ put(null, "panel:");
+ put(MarkupAdmonition.CAUTION, "note:");
+ put(MarkupAdmonition.IMPORTANT, "alert:");
+ put(MarkupAdmonition.NOTE, "info:");
+ put(MarkupAdmonition.TIP, "tip:");
+ put(MarkupAdmonition.WARNING, "warning:");
+ }};
public ConfluenceMarkupBuilder() {
super();
@@ -56,107 +83,123 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
@Override
public MarkupDocBuilder documentTitle(String title) {
+ Validate.notBlank(title, "title must not be null");
+ documentBuilder.append(String.format(TITLE_FORMAT, 0, title));
+ documentBuilder.append(newLine).append(newLine);
return this;
}
@Override
public MarkupDocBuilder sectionTitleWithAnchorLevel(int level, String title, String anchor) {
+ Validate.notBlank(title, "title must not be null");
+ Validate.inclusiveBetween(1, MAX_TITLE_LEVEL, level);
+
documentBuilder.append(newLine);
- documentBuilder.append("h").append(level + 1).append(". ").append(title);
+ documentBuilder.append(String.format(TITLE_FORMAT, level + 1, title));
if (isNotBlank(anchor)) {
- documentBuilder.append(" {anchor:").append(anchor).append("}");
+ documentBuilder.append(" ");
+ anchor(anchor);
+ documentBuilder.append(newLine);
}
- documentBuilder.append(newLine).append(newLine);
- return this;
- }
-
- @Override
- public MarkupDocBuilder block(String text, MarkupBlockStyle style, String title, MarkupAdmonition admonition) {
- switch (style) {
- case SIDEBAR:
- documentBuilder.append(newLine).append("{quote}").append(newLine);
- if (isNotBlank(title)) {
- documentBuilder.append(title);
- newLine(true);
- }
- documentBuilder.append(text);
- documentBuilder.append(newLine).append("{quote}").append(newLine);
- break;
- case EXAMPLE:
- case LITERAL:
- documentBuilder.append(newLine);
- if (isBlank(title)) {
- documentBuilder.append("{panel}");
- } else {
- documentBuilder.append("{panel:title=").append(title).append("}");
- }
- documentBuilder.append(newLine);
- documentBuilder.append(text);
- documentBuilder.append(newLine).append("{panel}").append(newLine);
- break;
- case LISTING:
- documentBuilder.append(newLine);
- if (isBlank(title)) {
- documentBuilder.append("{code}");
- } else {
- documentBuilder.append("{code:title=").append(title).append("}");
- }
- documentBuilder.append(newLine);
- documentBuilder.append(text);
- documentBuilder.append(newLine).append("{code}").append(newLine);
- break;
- case PASSTHROUGH:
- documentBuilder.append(newLine).append("{noformat}").append(newLine);
- if (isNotBlank(title)) {
- documentBuilder.append(title);
- documentBuilder.append(newLine);
- }
- documentBuilder.append(text);
- documentBuilder.append(newLine).append("{noformat}").append(newLine);
- break;
- }
- return this;
- }
-
- @Override
- public MarkupDocBuilder listing(String text, String language) {
documentBuilder.append(newLine);
- if (isBlank(language)) {
- documentBuilder.append("{code}");
+ return this;
+ }
+
+ @Override
+ public MarkupDocBuilder block(String text, final MarkupBlockStyle style, String title, MarkupAdmonition admonition) {
+
+ String block = BLOCK_STYLE.get(style);
+
+ boolean admonitionBlock = block.equals(">ADMONITION_BLOCK");
+ if (admonitionBlock) {
+ block = ADMONITION_BLOCK_STYLE.get(admonition);
+ }
+
+ boolean supportTitle = false;
+ if (block.endsWith(":")) {
+ supportTitle = true;
+ block = StringUtils.stripEnd(block, ":");
+ }
+
+ String titleString = null;
+ if (admonition != null && !admonitionBlock) {
+ titleString = StringUtils.capitalize(admonition.name().toLowerCase());
+ }
+ if (title != null) {
+ titleString = (titleString == null ? "" : titleString + " | ") + title;
+ }
+
+ final String finalBlock = block;
+ Markup blockMarkup = new Markup() {
+ @Override
+ public String toString() {
+ return String.format("{%s}", finalBlock);
+ }
+ };
+
+ if (!supportTitle) {
+ if (titleString != null)
+ documentBuilder.append(titleString).append(" : ").append(newLine);
+ delimitedBlockText(blockMarkup, text);
} else {
- documentBuilder.append("{code:language=").append(language).append("}");
+ final String finalTitleString = titleString;
+ delimitedBlockText(new Markup() {
+ @Override
+ public String toString() {
+ if (finalTitleString == null)
+ return String.format("{%s}", finalBlock);
+ else
+ return String.format("{%s:title=%s}", finalBlock, finalTitleString);
+ }
+ }, text, blockMarkup);
+ }
+
+ return this;
+ }
+
+ @Override
+ public MarkupDocBuilder listing(String text, final String language) {
+ Markup blockMarkup = new Markup() {
+ @Override
+ public String toString() {
+ return String.format("{%s}", "code");
+ }
+ };
+
+ if (language != null) {
+ delimitedBlockText(new Markup() {
+ @Override
+ public String toString() {
+ return String.format("{code:language=%s}", language);
+ }
+ }, text, blockMarkup);
+ } else {
+ delimitedBlockText(blockMarkup, text);
}
- documentBuilder.append(newLine);
- documentBuilder.append(text);
- documentBuilder.append(newLine).append("{code}").append(newLine).append(newLine);
return this;
}
@Override
public MarkupDocBuilder boldText(String text) {
- documentBuilder.append("*").append(text).append("*");
+ boldText(ConfluenceMarkup.BOLD, text);
return this;
}
@Override
public MarkupDocBuilder italicText(String text) {
- documentBuilder.append("_").append(text).append("_");
+ italicText(ConfluenceMarkup.ITALIC, text);
return this;
}
@Override
public MarkupDocBuilder unorderedList(List list) {
- documentBuilder.append(newLine).append(newLine);
- for (String item : list) {
- documentBuilder.append("* ").append(item).append(newLine);
- }
- documentBuilder.append(newLine);
+ unorderedList(ConfluenceMarkup.LIST_ENTRY, list);
return this;
}
@Override
public MarkupDocBuilder unorderedListItem(String item) {
- documentBuilder.append("* ").append(item);
+ unorderedListItem(ConfluenceMarkup.LIST_ENTRY, item);
return this;
}
@@ -172,9 +215,9 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
}
if (cells != null) {
for (List row : cells) {
- documentBuilder.append("|");
+ documentBuilder.append(ConfluenceMarkup.TABLE_COLUMN_DELIMITER);
for (String cell : row) {
- documentBuilder.append(escapeCellContent(cell)).append("|");
+ documentBuilder.append(escapeCellContent(cell)).append(ConfluenceMarkup.TABLE_COLUMN_DELIMITER);
}
documentBuilder.append(newLine);
}
@@ -186,7 +229,8 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
if (content == null) {
return " ";
}
- return content.replace("|", "\\|").replace(newLine, ConfluenceMarkup.LINE_BREAK.toString());
+ return content.replace(ConfluenceMarkup.TABLE_COLUMN_DELIMITER.toString(), ConfluenceMarkup.TABLE_COLUMN_DELIMITER_ESCAPE.toString())
+ .replace(newLine, ConfluenceMarkup.LINE_BREAK.toString());
}
private String normalizeAnchor(String anchor) {
@@ -196,13 +240,13 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
@Override
public MarkupDocBuilder anchor(String anchor, String text) {
- documentBuilder.append("{anchor:").append(normalizeAnchor(anchor)).append("}");
+ documentBuilder.append(ConfluenceMarkup.ANCHOR_START).append(normalizeAnchor(anchor)).append(ConfluenceMarkup.ANCHOR_END);
return this;
}
@Override
public MarkupDocBuilder crossReference(String document, String anchor, String text) {
- crossReferenceRaw(document, anchor, text);
+ crossReferenceRaw(document, normalizeAnchor(anchor), text);
return this;
}
@@ -212,7 +256,7 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
if (isNotBlank(document)) {
documentBuilder.append(document);
}
- documentBuilder.append("#").append(normalizeAnchor(anchor));
+ documentBuilder.append("#").append(anchor);
if (isNotBlank(text)) {
documentBuilder.append("|").append(text);
}
@@ -228,7 +272,7 @@ public final class ConfluenceMarkupBuilder extends AbstractMarkupDocBuilder {
@Override
public MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException {
- importMarkupStyle2(TITLE_PATTERN, "h%d. %s", false, markupText, levelOffset);
+ importMarkupStyle2(TITLE_PATTERN, TITLE_FORMAT, false, markupText, levelOffset);
return this;
}
diff --git a/src/main/java/io/github/robwin/markup/builder/internal/markdown/MarkdownBuilder.java b/src/main/java/io/github/robwin/markup/builder/internal/markdown/MarkdownBuilder.java
index 68b41577..71fce6a0 100644
--- a/src/main/java/io/github/robwin/markup/builder/internal/markdown/MarkdownBuilder.java
+++ b/src/main/java/io/github/robwin/markup/builder/internal/markdown/MarkdownBuilder.java
@@ -48,11 +48,11 @@ public class MarkdownBuilder extends AbstractMarkupDocBuilder {
private static final Pattern TITLE_PATTERN = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", Markdown.TITLE, MAX_TITLE_LEVEL + 1));
private static final Map BLOCK_STYLE = new HashMap() {{
- put(MarkupBlockStyle.EXAMPLE, null);
+ put(MarkupBlockStyle.EXAMPLE, "");
put(MarkupBlockStyle.LISTING, Markdown.LISTING.toString());
put(MarkupBlockStyle.LITERAL, Markdown.LISTING.toString());
- put(MarkupBlockStyle.PASSTHROUGH, null);
- put(MarkupBlockStyle.SIDEBAR, null);
+ put(MarkupBlockStyle.PASSTHROUGH, "");
+ put(MarkupBlockStyle.SIDEBAR, "");
}};
public MarkdownBuilder(){
@@ -94,19 +94,18 @@ public class MarkdownBuilder extends AbstractMarkupDocBuilder {
@Override
public MarkupDocBuilder block(String text, final MarkupBlockStyle style, String title, MarkupAdmonition admonition) {
if (admonition != null)
- documentBuilder.append(StringUtils.capitalize(admonition.name())).append(" : ");
+ documentBuilder.append(StringUtils.capitalize(admonition.name().toLowerCase()));
if (title != null) {
if (admonition != null)
documentBuilder.append(" | ");
- documentBuilder.append(title).append(" : ");
+ documentBuilder.append(title);
}
if (admonition != null || title != null)
- documentBuilder.append(newLine);
+ documentBuilder.append(" : ").append(newLine);
delimitedBlockText(new Markup() {
public String toString() {
- String separator = BLOCK_STYLE.get(style);
- return separator;
+ return BLOCK_STYLE.get(style);
}
}, text);
return this;
diff --git a/src/test/java/io/github/robwin/markup/builder/MarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/MarkupDocBuilderTest.java
index 5d0bb22b..3c66eecf 100644
--- a/src/test/java/io/github/robwin/markup/builder/MarkupDocBuilderTest.java
+++ b/src/test/java/io/github/robwin/markup/builder/MarkupDocBuilderTest.java
@@ -18,7 +18,6 @@
*/
package io.github.robwin.markup.builder;
-import io.github.robwin.markup.builder.internal.AbstractMarkupDocBuilder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -217,9 +216,9 @@ public class MarkupDocBuilderTest {
.anchor("anchor", "text").newLine()
.anchor(" Simple anchor").newLine()
.anchor(" \u0240 µ&|ù This .:/-_# ").newLine()
- .crossReferenceRaw("./document.md", "anchor", "text").newLine(true)
+ .crossReferenceRaw("./document.txt", "anchor", "text").newLine(true)
.crossReferenceRaw(" \u0240 µ&|ù This .:/-_ ").newLine(true)
- .crossReference("./document.md", "anchor", "text").newLine(true)
+ .crossReference("./document.txt", "anchor", "text").newLine(true)
.crossReference(" \u0240 µ&|ù This .:/-_ ").newLine(true);
builder.writeToFileWithoutExtension(builder.addFileExtension(Paths.get("build/tmp/test")), StandardCharsets.UTF_8);