From dddd5fc75c7fae7cb4b00a2fec3bd0b1a5c5e268 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Mon, 22 Feb 2016 13:47:13 +0100 Subject: [PATCH 1/5] MarkupTableColumn documentation enhancements --- .../markup/builder/MarkupTableColumn.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) 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 7de228d6..5a041574 100644 --- a/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java +++ b/src/main/java/io/github/robwin/markup/builder/MarkupTableColumn.java @@ -15,7 +15,8 @@ public class MarkupTableColumn { } /** - * Header constructor + * Header constructor. + * * @param header header name */ public MarkupTableColumn(String header) { @@ -23,7 +24,8 @@ public class MarkupTableColumn { } /** - * Header and specifiers constructor + * Header and specifiers constructor. + * * @param header header name * @param widthRatio width ratio */ @@ -33,7 +35,8 @@ public class MarkupTableColumn { } /** - * Set header name for this column + * Set header name for this column. + * * @param header header name * @return this builder */ @@ -43,7 +46,9 @@ public class MarkupTableColumn { } /** - * Set column width ratio for this column + * 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. * @return this builder */ @@ -53,9 +58,10 @@ public class MarkupTableColumn { } /** - * Overrides all other specifiers (for the specified language) with this language-dependent {@code specifiers} string + * Overrides all other specifiers (for the specified language) with this language-dependent {@code specifiers} string. + * * @param language apply the {@code specifiers} to this language only - * @param specifiers RAW language-dependent specifiers for the column + * @param specifiers RAW language-dependent specifiers string for the column * @return this builder */ public MarkupTableColumn withMarkupSpecifiers(MarkupLanguage language, String specifiers) { From 038edb8d946458461517c411bb8657c7e1cfc31f Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Mon, 22 Feb 2016 20:36:50 +0100 Subject: [PATCH 2/5] Added importMarkup(markupText, levelOffset) --- .../builder/AbstractMarkupDocBuilder.java | 33 ++++++++++++ .../markup/builder/MarkupDocBuilder.java | 19 +++++++ .../markup/builder/asciidoc/AsciiDoc.java | 1 + .../builder/asciidoc/AsciiDocBuilder.java | 6 +++ .../markup/builder/markdown/Markdown.java | 1 + .../builder/markdown/MarkdownBuilder.java | 10 ++++ .../builder/AbstractMarkupDocBuilderTest.java | 50 +++++++++++++++++++ 7 files changed, 120 insertions(+) diff --git a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java index d33e0380..d8e3a435 100644 --- a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java @@ -30,6 +30,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.text.Normalizer; import java.util.List; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.apache.commons.lang3.StringUtils.defaultString; @@ -47,6 +48,7 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { private static final Pattern ANCHOR_UNIGNORABLE_PATTERN = Pattern.compile("[^0-9a-zA-Z-_]+"); private static final Pattern ANCHOR_IGNORABLE_PATTERN = Pattern.compile("[\\s@#&(){}\\[\\]!$*%+=/:.;,?\\\\<>|]+"); private static final String ANCHOR_SEPARATION_CHARACTERS = "_-"; + private static final int MAX_TITLE_LEVEL = 5; protected StringBuilder documentBuilder = new StringBuilder(); protected String newLine = System.getProperty("line.separator"); @@ -265,6 +267,34 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { return this; } + @Override + public MarkupDocBuilder importMarkup(String text) { + return importMarkup(text, 0); + } + + protected void importMarkup(Markup titlePrefix, String text, int levelOffset) { + if (levelOffset > MAX_TITLE_LEVEL) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max title level (%d)", levelOffset, MAX_TITLE_LEVEL)); + + StringBuffer leveledText = new StringBuffer(); + Matcher sections = Pattern.compile(String.format("^(%s{1,%d})(\\s+.*)$", titlePrefix, MAX_TITLE_LEVEL), Pattern.MULTILINE).matcher(text); + + while (sections.find()) { + int titleLevel = sections.group(1).length(); + String title = sections.group(2); + + if (titleLevel + levelOffset > MAX_TITLE_LEVEL) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); + else + sections.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), titleLevel + levelOffset) + title); + } + sections.appendTail(leveledText); + + documentBuilder.append(newLine); + documentBuilder.append(leveledText.toString()); + documentBuilder.append(newLine); + } + @Override public MarkupDocBuilder table(List> cells) { return tableWithColumnSpecs(null, cells); @@ -279,6 +309,9 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { return fileName + "." + markup; } + /** + * 2 newLines are needed at the end of file for file to be included without protection. + */ @Override public void writeToFileWithoutExtension(String directory, String fileName, Charset charset) throws IOException { Files.createDirectories(Paths.get(directory)); diff --git a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java index b885988d..460b67b0 100644 --- a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java @@ -386,6 +386,25 @@ public interface MarkupDocBuilder { */ MarkupDocBuilder newLine(boolean forceLineBreak); + /** + * Import some markup text into this builder.
+ * This is an alias for {@link #importMarkup(String, int) importMarkup(text, 0)}. + * + * @param text markup text to import + * @return this builder + */ + MarkupDocBuilder importMarkup(String text); + + /** + * Import some markup text into this builder. + * + * @param markupText markup text to import + * @param levelOffset adapt section leveling by adding {@code levelOffset} [0-5] + * @return this builder + * @throws IllegalArgumentException if levelOffset is too high for the imported markup + */ + MarkupDocBuilder importMarkup(String markupText, int levelOffset); + /** * Returns a string representation of the document. */ diff --git a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDoc.java b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDoc.java index 590c7bbe..9a297ac8 100644 --- a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDoc.java +++ b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDoc.java @@ -31,6 +31,7 @@ public enum AsciiDoc implements Markup { TABLE_COLUMN_DELIMITER_ESCAPE("\\|"), // AsciiDoctor supports both \| and {vbar} LISTING("----"), HARDBREAKS("[%hardbreaks]"), + TITLE("="), DOCUMENT_TITLE("= "), SECTION_TITLE_LEVEL1("== "), SECTION_TITLE_LEVEL2("=== "), diff --git a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java index 3a8e5bb3..15ba3cf7 100644 --- a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java @@ -254,6 +254,12 @@ public class AsciiDocBuilder extends AbstractMarkupDocBuilder { return this; } + @Override + public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + importMarkup(AsciiDoc.TITLE, markupText, levelOffset); + return this; + } + @Override public String addfileExtension(String fileName) { return addfileExtension(AsciiDoc.FILE_EXTENSION, fileName); diff --git a/src/main/java/io/github/robwin/markup/builder/markdown/Markdown.java b/src/main/java/io/github/robwin/markup/builder/markdown/Markdown.java index 94fe3c64..f42d9f39 100644 --- a/src/main/java/io/github/robwin/markup/builder/markdown/Markdown.java +++ b/src/main/java/io/github/robwin/markup/builder/markdown/Markdown.java @@ -29,6 +29,7 @@ public enum Markdown implements Markup { TABLE_COLUMN_DELIMITER_ESCAPE("\\|"), TABLE_ROW("-"), LISTING("```"), + TITLE("#"), DOCUMENT_TITLE("# "), SECTION_TITLE_LEVEL1("## "), SECTION_TITLE_LEVEL2("### "), diff --git a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java index bacc72bb..2e0166db 100644 --- a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java @@ -29,6 +29,7 @@ import org.apache.commons.lang3.Validate; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.regex.Pattern; import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.join; @@ -38,6 +39,9 @@ import static org.apache.commons.lang3.StringUtils.join; */ public class MarkdownBuilder extends AbstractMarkupDocBuilder { + private static final int MAX_TITLE_LEVEL = 5; + private static final char TITLE_PREFIX = '#'; + private static Pattern TITLE_PATTERN = Pattern.compile(String.format("^%c({1,%d})( .*)$", TITLE_PREFIX, MAX_TITLE_LEVEL)); @Override public MarkupDocBuilder copy() { @@ -243,6 +247,12 @@ public class MarkdownBuilder extends AbstractMarkupDocBuilder return this; } + @Override + public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + importMarkup(Markdown.TITLE, markupText, levelOffset); + return this; + } + @Override public String addfileExtension(String fileName) { return addfileExtension(Markdown.FILE_EXTENSION, fileName); diff --git a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java index a83640b7..c33a023d 100644 --- a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java +++ b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java @@ -8,6 +8,7 @@ import org.junit.Test; import org.mockito.Mockito; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; public class AbstractMarkupDocBuilderTest { @@ -17,6 +18,8 @@ public class AbstractMarkupDocBuilderTest { @Before public void setUp() { builder = mock(AbstractMarkupDocBuilder.class, Mockito.CALLS_REAL_METHODS); + builder.newLine = System.getProperty("line.separator"); + builder.documentBuilder = new StringBuilder(); } private String normalize(Markup markup, String anchor) { @@ -64,4 +67,51 @@ public class AbstractMarkupDocBuilderTest { assertNormalization(Markdown.SPACE_ESCAPE, "", " @#&(){}[]!$*%+=/:.;,?\\<>| "); assertNormalization(Markdown.SPACE_ESCAPE, "sub-action-html-query-value", " /sub/action.html/?query=value "); } + + private void assertImportMarkup(Markup markup, String expected, String text, int levelOffset) { + builder.documentBuilder = new StringBuilder(); + builder.importMarkup(markup, text, levelOffset); + assertEquals(expected, builder.documentBuilder.toString()); + } + + private void assertImportMarkupException(Markup markup, String expected, String text, int levelOffset) { + builder.documentBuilder = new StringBuilder(); + try { + builder.importMarkup(markup, text, levelOffset); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + assertEquals(expected, e.getMessage()); + } + } + + @Test + public void testImportMarkupAsciiDoc() { + assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 0); + assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 5); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "= title\nline 1\nline 2", 0); + assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n", "= title\nline 1\nline 2", 4); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "= title\nline 1\nline 2", 5); + } + + @Test + public void testImportMarkupMarkdown() { + assertImportMarkup(Markdown.TITLE, "\n\n", "", 0); + assertImportMarkup(Markdown.TITLE, "\n\n", "", 5); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "# title\nline 1\nline 2", 0); + assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n", "# title\nline 1\nline 2", 4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "# title\nline 1\nline 2", 5); + } + } \ No newline at end of file From 689505e0d7817a29d25af4627b531df30b9b405f Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Mon, 22 Feb 2016 20:42:12 +0100 Subject: [PATCH 3/5] Check for levelOffset < 0 in importMarkup(markupText, levelOffset) --- .../robwin/markup/builder/AbstractMarkupDocBuilder.java | 2 ++ .../robwin/markup/builder/AbstractMarkupDocBuilderTest.java | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java index d8e3a435..a4f8299b 100644 --- a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java @@ -275,6 +275,8 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { protected void importMarkup(Markup titlePrefix, String text, int levelOffset) { if (levelOffset > MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max title level (%d)", levelOffset, MAX_TITLE_LEVEL)); + if (levelOffset < 0) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) < 0", levelOffset)); StringBuffer leveledText = new StringBuffer(); Matcher sections = Pattern.compile(String.format("^(%s{1,%d})(\\s+.*)$", titlePrefix, MAX_TITLE_LEVEL), Pattern.MULTILINE).matcher(text); diff --git a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java index c33a023d..65793d77 100644 --- a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java +++ b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java @@ -89,14 +89,17 @@ public class AbstractMarkupDocBuilderTest { assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 0); assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 5); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "", -1); assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "", -1); assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "= title\nline 1\nline 2", 0); assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n", "= title\nline 1\nline 2", 4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "= title\nline 1\nline 2", 5); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "= title\nline 1\nline 2", -1); } @Test @@ -104,14 +107,17 @@ public class AbstractMarkupDocBuilderTest { assertImportMarkup(Markdown.TITLE, "\n\n", "", 0); assertImportMarkup(Markdown.TITLE, "\n\n", "", 5); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "", -1); assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "", -1); assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "# title\nline 1\nline 2", 0); assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n", "# title\nline 1\nline 2", 4); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "# title\nline 1\nline 2", 5); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "= title\nline 1\nline 2", -1); } } \ No newline at end of file From 913b100f6b9ae5565b4ce7fa3b3d3385497f5fb3 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Tue, 23 Feb 2016 12:42:54 +0100 Subject: [PATCH 4/5] Support for levelOffset < 0 in importMarkup --- .../builder/AbstractMarkupDocBuilder.java | 16 +++++---- .../builder/AbstractMarkupDocBuilderTest.java | 36 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java index a4f8299b..9da2e8dd 100644 --- a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java @@ -48,7 +48,7 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { private static final Pattern ANCHOR_UNIGNORABLE_PATTERN = Pattern.compile("[^0-9a-zA-Z-_]+"); private static final Pattern ANCHOR_IGNORABLE_PATTERN = Pattern.compile("[\\s@#&(){}\\[\\]!$*%+=/:.;,?\\\\<>|]+"); private static final String ANCHOR_SEPARATION_CHARACTERS = "_-"; - private static final int MAX_TITLE_LEVEL = 5; + private static final int MAX_TITLE_LEVEL = 4; protected StringBuilder documentBuilder = new StringBuilder(); protected String newLine = System.getProperty("line.separator"); @@ -274,21 +274,23 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { protected void importMarkup(Markup titlePrefix, String text, int levelOffset) { if (levelOffset > MAX_TITLE_LEVEL) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max title level (%d)", levelOffset, MAX_TITLE_LEVEL)); - if (levelOffset < 0) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) < 0", levelOffset)); + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max levelOffset (%d)", levelOffset, MAX_TITLE_LEVEL)); + if (levelOffset < -MAX_TITLE_LEVEL) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) < min levelOffset (%d)", levelOffset, -MAX_TITLE_LEVEL)); StringBuffer leveledText = new StringBuffer(); - Matcher sections = Pattern.compile(String.format("^(%s{1,%d})(\\s+.*)$", titlePrefix, MAX_TITLE_LEVEL), Pattern.MULTILINE).matcher(text); + Matcher sections = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", titlePrefix, MAX_TITLE_LEVEL + 1), Pattern.MULTILINE).matcher(text); while (sections.find()) { - int titleLevel = sections.group(1).length(); + int titleLevel = sections.group(1).length() - 1; String title = sections.group(2); if (titleLevel + levelOffset > MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); + if (titleLevel + levelOffset < 0) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) < 0", levelOffset, title, titleLevel)); else - sections.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), titleLevel + levelOffset) + title); + sections.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), 1 + titleLevel + levelOffset) + " " + title); } sections.appendTail(leveledText); diff --git a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java index 65793d77..f7985f7f 100644 --- a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java +++ b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java @@ -87,37 +87,41 @@ public class AbstractMarkupDocBuilderTest { @Test public void testImportMarkupAsciiDoc() { assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 0); - assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 5); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "", -1); + assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 4); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); + assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", -4); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "", -1); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "= title\nline 1\nline 2", 0); assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n", "= title\nline 1\nline 2", 4); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "= title\nline 1\nline 2", 5); - assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) < 0", "= title\nline 1\nline 2", -1); + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "===== title\nline 1\nline 2", -4); + + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "== title\nline 1\nline 2", 4); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "= title\nline 1\nline 2", -1); + assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-3) set title 'title' level (1) < 0", "== title\nline 1\nline 2", -3); } @Test public void testImportMarkupMarkdown() { assertImportMarkup(Markdown.TITLE, "\n\n", "", 0); - assertImportMarkup(Markdown.TITLE, "\n\n", "", 5); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "", -1); + assertImportMarkup(Markdown.TITLE, "\n\n", "", 4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); + assertImportMarkup(Markdown.TITLE, "\n\n", "", -4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 5); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (6) > max title level (5)", "", 6); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "", -1); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "# title\nline 1\nline 2", 0); assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n", "# title\nline 1\nline 2", 4); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) set title ' title' level (1) > max title level (5)", "# title\nline 1\nline 2", 5); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) < 0", "= title\nline 1\nline 2", -1); + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "##### title\nline 1\nline 2", -4); + + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "## title\nline 1\nline 2", 4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "# title\nline 1\nline 2", -1); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-3) set title 'title' level (1) < 0", "## title\nline 1\nline 2", -3); } } \ No newline at end of file From c9d7f701e717331dfd060d487fcca546e838b558 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Tue, 23 Feb 2016 13:55:37 +0100 Subject: [PATCH 5/5] Use Reader in importMarkup instead of a String --- .../builder/AbstractMarkupDocBuilder.java | 38 ++++++++++------- .../markup/builder/MarkupDocBuilder.java | 15 ++++--- .../builder/asciidoc/AsciiDocBuilder.java | 4 +- .../builder/markdown/MarkdownBuilder.java | 4 +- .../builder/AbstractMarkupDocBuilderTest.java | 41 +++++++++++-------- 5 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java index 9da2e8dd..985d58d1 100644 --- a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java @@ -23,8 +23,10 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; +import java.io.Reader; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; @@ -268,31 +270,39 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { } @Override - public MarkupDocBuilder importMarkup(String text) { - return importMarkup(text, 0); + public MarkupDocBuilder importMarkup(Reader markupText) throws IOException { + return importMarkup(markupText, 0); } - protected void importMarkup(Markup titlePrefix, String text, int levelOffset) { + protected void importMarkup(Markup titlePrefix, Reader markupText, int levelOffset) throws IOException { if (levelOffset > MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max levelOffset (%d)", levelOffset, MAX_TITLE_LEVEL)); if (levelOffset < -MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) < min levelOffset (%d)", levelOffset, -MAX_TITLE_LEVEL)); + final Pattern titlePattern = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", titlePrefix, MAX_TITLE_LEVEL + 1)); + StringBuffer leveledText = new StringBuffer(); - Matcher sections = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", titlePrefix, MAX_TITLE_LEVEL + 1), Pattern.MULTILINE).matcher(text); + try (BufferedReader bufferedReader = new BufferedReader(markupText)) { + String readLine; + while ((readLine = bufferedReader.readLine()) != null) { + Matcher titleMatcher = titlePattern.matcher(readLine); - while (sections.find()) { - int titleLevel = sections.group(1).length() - 1; - String title = sections.group(2); + while (titleMatcher.find()) { + int titleLevel = titleMatcher.group(1).length() - 1; + String title = titleMatcher.group(2); - if (titleLevel + levelOffset > MAX_TITLE_LEVEL) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); - if (titleLevel + levelOffset < 0) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) < 0", levelOffset, title, titleLevel)); - else - sections.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), 1 + titleLevel + levelOffset) + " " + title); + if (titleLevel + levelOffset > MAX_TITLE_LEVEL) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); + if (titleLevel + levelOffset < 0) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) < 0", levelOffset, title, titleLevel)); + else + titleMatcher.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), 1 + titleLevel + levelOffset) + " " + title); + } + titleMatcher.appendTail(leveledText); + leveledText.append(newLine); + } } - sections.appendTail(leveledText); documentBuilder.append(newLine); documentBuilder.append(leveledText.toString()); diff --git a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java index 460b67b0..90fa6e80 100644 --- a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java @@ -19,6 +19,7 @@ package io.github.robwin.markup.builder; import java.io.IOException; +import java.io.Reader; import java.nio.charset.Charset; import java.util.List; @@ -388,22 +389,26 @@ public interface MarkupDocBuilder { /** * Import some markup text into this builder.
- * This is an alias for {@link #importMarkup(String, int) importMarkup(text, 0)}. + * This is an alias for {@link #importMarkup(Reader, int) importMarkup(markupText, 0)}. + * Newlines are normalized in the process. * - * @param text markup text to import + * @param markupText markup reader to read data from * @return this builder + * @throws IOException if I/O error occurs while reading {@code markupText} */ - MarkupDocBuilder importMarkup(String text); + MarkupDocBuilder importMarkup(Reader markupText) throws IOException; /** * Import some markup text into this builder. + * Newlines are normalized in the process. * - * @param markupText markup text to import + * @param markupText markup reader to read data from * @param levelOffset adapt section leveling by adding {@code levelOffset} [0-5] * @return this builder * @throws IllegalArgumentException if levelOffset is too high for the imported markup + * @throws IOException if I/O error occurs while reading {@code markupText} */ - MarkupDocBuilder importMarkup(String markupText, int levelOffset); + MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException; /** * Returns a string representation of the document. diff --git a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java index 15ba3cf7..418dee57 100644 --- a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java @@ -27,6 +27,8 @@ import io.github.robwin.markup.builder.MarkupTableColumn; import org.apache.commons.collections.CollectionUtils; import java.io.File; +import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -255,7 +257,7 @@ public class AsciiDocBuilder extends AbstractMarkupDocBuilder { } @Override - public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + public MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException { importMarkup(AsciiDoc.TITLE, markupText, levelOffset); return this; } diff --git a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java index 2e0166db..3b195233 100644 --- a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java @@ -26,6 +26,8 @@ import io.github.robwin.markup.builder.MarkupTableColumn; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; +import java.io.IOException; +import java.io.Reader; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -248,7 +250,7 @@ public class MarkdownBuilder extends AbstractMarkupDocBuilder } @Override - public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + public MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException { importMarkup(Markdown.TITLE, markupText, levelOffset); return this; } diff --git a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java index f7985f7f..acd583e0 100644 --- a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java +++ b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java @@ -7,6 +7,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import java.io.IOException; +import java.io.StringReader; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; @@ -68,16 +71,16 @@ public class AbstractMarkupDocBuilderTest { assertNormalization(Markdown.SPACE_ESCAPE, "sub-action-html-query-value", " /sub/action.html/?query=value "); } - private void assertImportMarkup(Markup markup, String expected, String text, int levelOffset) { + private void assertImportMarkup(Markup markup, String expected, String text, int levelOffset) throws IOException { builder.documentBuilder = new StringBuilder(); - builder.importMarkup(markup, text, levelOffset); + builder.importMarkup(markup, new StringReader(text), levelOffset); assertEquals(expected, builder.documentBuilder.toString()); } - private void assertImportMarkupException(Markup markup, String expected, String text, int levelOffset) { + private void assertImportMarkupException(Markup markup, String expected, String text, int levelOffset) throws IOException { builder.documentBuilder = new StringBuilder(); try { - builder.importMarkup(markup, text, levelOffset); + builder.importMarkup(markup, new StringReader(text), levelOffset); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException e) { assertEquals(expected, e.getMessage()); @@ -85,19 +88,21 @@ public class AbstractMarkupDocBuilderTest { } @Test - public void testImportMarkupAsciiDoc() { + public void testImportMarkupAsciiDoc() throws IOException { assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 0); assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", -4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); - assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n\n", "= title\r\nline 1\r\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "= title\nline 1\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n", "= title\nline 1\nline 2", 4); - assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "===== title\nline 1\nline 2", -4); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 0); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 4); + + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n= title 2\nline 3\n\n", "= title\nline 1\nline 2\n= title 2\nline 3", 0); + assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n\n", "= title\nline 1\nline 2", 4); + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n\n", "===== title\nline 1\nline 2", -4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "== title\nline 1\nline 2", 4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "= title\nline 1\nline 2", -1); @@ -105,19 +110,21 @@ public class AbstractMarkupDocBuilderTest { } @Test - public void testImportMarkupMarkdown() { + public void testImportMarkupMarkdown() throws IOException { assertImportMarkup(Markdown.TITLE, "\n\n", "", 0); assertImportMarkup(Markdown.TITLE, "\n\n", "", 4); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkup(Markdown.TITLE, "\n\n", "", -4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); - assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n\n", "# title\r\nline 1\r\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "# title\nline 1\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n", "# title\nline 1\nline 2", 4); - assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "##### title\nline 1\nline 2", -4); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 0); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 4); + + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n# title 2\nline 3\n\n", "# title\nline 1\nline 2\n# title 2\nline 3", 0); + assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n\n", "# title\nline 1\nline 2", 4); + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n\n", "##### title\nline 1\nline 2", -4); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "## title\nline 1\nline 2", 4); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "# title\nline 1\nline 2", -1);