diff options
6 files changed, 40 insertions, 7 deletions
diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/ParagraphMatcher.java b/src/main/java/org/zwobble/mammoth/internal/styles/ParagraphMatcher.java index 82f2a78..914d7de 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/ParagraphMatcher.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/ParagraphMatcher.java @@ -13,7 +13,11 @@ public class ParagraphMatcher implements DocumentElementMatcher<Paragraph> { } public static ParagraphMatcher styleName(String styleName) { - return new ParagraphMatcher(Optional.empty(), Optional.of(new EqualToStringMatcher(styleName)), Optional.empty()); + return styleName(new EqualToStringMatcher(styleName)); + } + + public static ParagraphMatcher styleName(StringMatcher styleName) { + return new ParagraphMatcher(Optional.empty(), Optional.of(styleName), Optional.empty()); } public static ParagraphMatcher orderedList(String level) { diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java index ff96a55..7615e65 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java @@ -52,15 +52,24 @@ public class DocumentMatcherParser { private static Optional<StringMatcher> parseStyleName(TokenIterator<TokenType> tokens) { if (tokens.trySkip(TokenType.SYMBOL, "[")) { tokens.skip(TokenType.IDENTIFIER, "style-name"); - tokens.skip(TokenType.SYMBOL, "="); - String value = TokenParser.parseString(tokens); + StringMatcher stringMatcher = parseStringMatcher(tokens); tokens.skip(TokenType.SYMBOL, "]"); - return Optional.of(new EqualToStringMatcher(value)); + return Optional.of(stringMatcher); } else { return Optional.empty(); } } + private static StringMatcher parseStringMatcher(TokenIterator<TokenType> tokens) { + if (tokens.trySkip(TokenType.SYMBOL, "=")) { + return new EqualToStringMatcher(TokenParser.parseString(tokens)); + } else if (tokens.trySkip(TokenType.SYMBOL, "^=")) { + return new StartsWithStringMatcher(TokenParser.parseString(tokens)); + } else { + throw new LineParseException(tokens.next(), "Expected string matcher but got token " + tokens.next().getValue()); + } + } + private static Optional<NumberingLevel> parseNumbering(TokenIterator<TokenType> tokens) { if (tokens.trySkip(TokenType.SYMBOL, ":")) { boolean isOrdered = parseListType(tokens); diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java index 50fcffe..9dc2d4d 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java @@ -13,7 +13,7 @@ public class StyleMappingTokeniser { TokenType.UNKNOWN, list( RegexTokeniser.rule(TokenType.IDENTIFIER, identifierCharacter + "(?:" + identifierCharacter + "|[0-9])*"), - RegexTokeniser.rule(TokenType.SYMBOL, ":|>|=>|=|\\(|\\)|\\[|\\]|\\||!|\\."), + RegexTokeniser.rule(TokenType.SYMBOL, ":|>|=>|\\^=|=|\\(|\\)|\\[|\\]|\\||!|\\."), RegexTokeniser.rule(TokenType.WHITESPACE, "\\s+"), RegexTokeniser.rule(TokenType.STRING, stringPrefix + "'"), RegexTokeniser.rule(TokenType.UNTERMINATED_STRING, stringPrefix), diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java index 7ac7643..e1226ee 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java @@ -38,6 +38,10 @@ public class TokenIterator<T> { return tokens.get(index).getTokenType(); } + public Token<T> next() { + return tokens.get(index++); + } + public Token<T> next(T type) { Token<T> token = tokens.get(index); if (token.getTokenType() == type) { diff --git a/src/test/java/org/zwobble/mammoth/tests/styles/parsing/DocumentMatcherParsingTests.java b/src/test/java/org/zwobble/mammoth/tests/styles/parsing/DocumentMatcherParsingTests.java index 3c00909..0ee863a 100644 --- a/src/test/java/org/zwobble/mammoth/tests/styles/parsing/DocumentMatcherParsingTests.java +++ b/src/test/java/org/zwobble/mammoth/tests/styles/parsing/DocumentMatcherParsingTests.java @@ -1,8 +1,10 @@ package org.zwobble.mammoth.tests.styles.parsing; import org.junit.Test; +import org.zwobble.mammoth.internal.styles.EqualToStringMatcher; import org.zwobble.mammoth.internal.styles.ParagraphMatcher; import org.zwobble.mammoth.internal.styles.RunMatcher; +import org.zwobble.mammoth.internal.styles.StartsWithStringMatcher; import org.zwobble.mammoth.internal.styles.parsing.DocumentMatcherParser; import org.zwobble.mammoth.internal.styles.parsing.StyleMappingTokeniser; import org.zwobble.mammoth.internal.styles.parsing.TokenIterator; @@ -27,10 +29,19 @@ public class DocumentMatcherParsingTests { } @Test - public void readsParagraphWithStyleName() { + public void readsParagraphWithExactStyleName() { assertThat( parseParagraphMatcher("p[style-name='Heading 1']"), - deepEquals(ParagraphMatcher.styleName("Heading 1"))); + deepEquals(ParagraphMatcher.styleName(new EqualToStringMatcher("Heading 1"))) + ); + } + + @Test + public void readsParagraphWithStyleNamePrefix() { + assertThat( + parseParagraphMatcher("p[style-name^='Heading']"), + deepEquals(ParagraphMatcher.styleName(new StartsWithStringMatcher("Heading"))) + ); } @Test diff --git a/src/test/java/org/zwobble/mammoth/tests/styles/parsing/StyleMappingTokeniserTests.java b/src/test/java/org/zwobble/mammoth/tests/styles/parsing/StyleMappingTokeniserTests.java index e4e1f9b..f3147ba 100644 --- a/src/test/java/org/zwobble/mammoth/tests/styles/parsing/StyleMappingTokeniserTests.java +++ b/src/test/java/org/zwobble/mammoth/tests/styles/parsing/StyleMappingTokeniserTests.java @@ -81,6 +81,11 @@ public class StyleMappingTokeniserTests { } @Test + public void startsWithSymbolsAreTokenised() { + assertTokens("^=^=", isToken(TokenType.SYMBOL, "^="), isToken(TokenType.SYMBOL, "^=")); + } + + @Test public void openParensAreTokenised() { assertTokens("((", isToken(TokenType.SYMBOL, "("), isToken(TokenType.SYMBOL, "(")); } |
