Optional allow only one $ around the latex
This commit is contained in:
		
							parent
							
								
									2ea148c30a
								
							
						
					
					
						commit
						f711d6d702
					
				@ -1,11 +1,11 @@
 | 
			
		||||
package io.noties.markwon.ext.latex;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
import org.commonmark.node.Node;
 | 
			
		||||
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.annotation.VisibleForTesting;
 | 
			
		||||
import io.noties.markwon.inlineparser.InlineProcessor;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -13,7 +13,24 @@ import io.noties.markwon.inlineparser.InlineProcessor;
 | 
			
		||||
 */
 | 
			
		||||
class JLatexMathInlineProcessor extends InlineProcessor {
 | 
			
		||||
 | 
			
		||||
    private static final Pattern RE = Pattern.compile("(\\${2})([\\s\\S]+?)\\1");
 | 
			
		||||
    private static final Pattern singleOrDoubleDollar =
 | 
			
		||||
        Pattern.compile("(\\${2})([\\s\\S]+?)(\\${2})|(\\$)([\\s\\S]+?)(\\$)");
 | 
			
		||||
    private static final Pattern doubleDollar =
 | 
			
		||||
        Pattern.compile("(\\${2})([\\s\\S]+?)\\1");
 | 
			
		||||
 | 
			
		||||
    private final boolean allowSingle$;
 | 
			
		||||
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    final Pattern pattern;
 | 
			
		||||
 | 
			
		||||
    JLatexMathInlineProcessor() {
 | 
			
		||||
        this(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    JLatexMathInlineProcessor(boolean allowSingle$) {
 | 
			
		||||
        this.allowSingle$ = allowSingle$;
 | 
			
		||||
        this.pattern = allowSingle$ ? singleOrDoubleDollar : doubleDollar;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public char specialCharacter() {
 | 
			
		||||
@ -24,13 +41,25 @@ class JLatexMathInlineProcessor extends InlineProcessor {
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Node parse() {
 | 
			
		||||
 | 
			
		||||
        final String latex = match(RE);
 | 
			
		||||
        final String latex = match(pattern);
 | 
			
		||||
        if (latex == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final JLatexMathNode node = new JLatexMathNode();
 | 
			
		||||
        node.latex(latex.substring(2, latex.length() - 2));
 | 
			
		||||
        node.latex(trimDollar(latex));
 | 
			
		||||
        return node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("DuplicateExpressions")
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    String trimDollar(String latex) {
 | 
			
		||||
        if (allowSingle$) {
 | 
			
		||||
            return latex.startsWith("$$") && latex.endsWith("$$")
 | 
			
		||||
                ? latex.substring(2, latex.length() - 2)
 | 
			
		||||
                : latex.substring(1, latex.length() - 1);
 | 
			
		||||
        } else {
 | 
			
		||||
            return latex.substring(2, latex.length() - 2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -119,6 +119,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
 | 
			
		||||
        final boolean blocksEnabled;
 | 
			
		||||
        final boolean blocksLegacy;
 | 
			
		||||
        final boolean inlinesEnabled;
 | 
			
		||||
        final boolean allowInlineSingle$;
 | 
			
		||||
 | 
			
		||||
        // @since 4.3.0
 | 
			
		||||
        final ErrorHandler errorHandler;
 | 
			
		||||
@ -130,6 +131,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
 | 
			
		||||
            this.blocksEnabled = builder.blocksEnabled;
 | 
			
		||||
            this.blocksLegacy = builder.blocksLegacy;
 | 
			
		||||
            this.inlinesEnabled = builder.inlinesEnabled;
 | 
			
		||||
            this.allowInlineSingle$ = builder.allowInlineSingle$;
 | 
			
		||||
            this.errorHandler = builder.errorHandler;
 | 
			
		||||
            // @since 4.0.0
 | 
			
		||||
            ExecutorService executorService = builder.executorService;
 | 
			
		||||
@ -160,7 +162,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
 | 
			
		||||
        if (config.inlinesEnabled) {
 | 
			
		||||
            registry.require(MarkwonInlineParserPlugin.class)
 | 
			
		||||
                    .factoryBuilder()
 | 
			
		||||
                    .addInlineProcessor(new JLatexMathInlineProcessor());
 | 
			
		||||
                    .addInlineProcessor(new JLatexMathInlineProcessor(config.allowInlineSingle$));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -285,6 +287,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
 | 
			
		||||
        private boolean blocksEnabled = true;
 | 
			
		||||
        private boolean blocksLegacy;
 | 
			
		||||
        private boolean inlinesEnabled;
 | 
			
		||||
        private boolean allowInlineSingle$;
 | 
			
		||||
 | 
			
		||||
        // @since 4.3.0
 | 
			
		||||
        private ErrorHandler errorHandler;
 | 
			
		||||
@ -331,6 +334,16 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param inlineSingleDollar indicates if $xxx$ is valid.
 | 
			
		||||
         * @since 4.7.0
 | 
			
		||||
         */
 | 
			
		||||
        @NonNull
 | 
			
		||||
        public Builder allowInlinesSingleDollar(boolean inlineSingleDollar){
 | 
			
		||||
            this.allowInlineSingle$ = inlineSingleDollar;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull
 | 
			
		||||
        public Builder errorHandler(@Nullable ErrorHandler errorHandler) {
 | 
			
		||||
            this.errorHandler = errorHandler;
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
package io.noties.markwon.ext.latex;
 | 
			
		||||
 | 
			
		||||
import org.junit.Assert;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.junit.runners.Parameterized;
 | 
			
		||||
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author YvesCheung
 | 
			
		||||
 * 2023/6/14
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(Parameterized.class)
 | 
			
		||||
public class JLatexMathInlineParserTest {
 | 
			
		||||
 | 
			
		||||
    @Parameterized.Parameters
 | 
			
		||||
    public static Object[][] data() {
 | 
			
		||||
        return new Object[][]{
 | 
			
		||||
            {true, "$ a $", "$ a $", " a "},
 | 
			
		||||
            {false, "$ a $", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "ashdksa $ a $sfalhs", "$ a $", " a "},
 | 
			
		||||
            {false, "ashdksa $ a $sfalhs", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "c sajdl asjkdhk $abc$\n sahdila", "$abc$", "abc"},
 | 
			
		||||
            {false, "c sajdl asjkdhk $abc$\n sahdila", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "c sajdl asjkdhk \n$abcd $ sahdila", "$abcd $", "abcd "},
 | 
			
		||||
            {false, "c sajdl asjkdhk \n$abcd $ sahdila", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "$$abc$$", "$$abc$$", "abc"},
 | 
			
		||||
            {false, "$$abc$$", "$$abc$$", "abc"},
 | 
			
		||||
 | 
			
		||||
            {true, "$$abc$", "$$abc$", "$abc"},
 | 
			
		||||
            {false, "$$abc$", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "lllll bbb xxx $dhaksdhk\n asd ${b}", "$dhaksdhk\n asd $", "dhaksdhk\n asd "},
 | 
			
		||||
            {false, "lllll bbb xxx $dhaksdhk\n asd ${b}", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "aaa yyy $$bb $ dddd$", "$$bb $", "$bb "},
 | 
			
		||||
            {false, "aaa yyy $$bb $ dddd$", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "aaa $sagdkg$$ Hello", "$sagdkg$", "sagdkg"},
 | 
			
		||||
            {false, "aaa $sagdkg$$ Hello", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "lllll bbb xxx dhaksdhk\n asd ${b}", "", ""},
 | 
			
		||||
            {false, "lllll bbb xxx dhaksdhk\n asd ${b}", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "asdhfalkhasl suaflhslia lasdjikaih sahk", "", ""},
 | 
			
		||||
            {false, "asdhfalkhasl suaflhslia lasdjikaih sahk", "", ""},
 | 
			
		||||
 | 
			
		||||
            {true, "lllll bbb $xxx dhaksdhk\n asd", "", ""},
 | 
			
		||||
            {false, "lllll bbb $xxx dhaksdhk\n asd", "", ""}
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Parameterized.Parameter(0)
 | 
			
		||||
    public boolean allowSingle$;
 | 
			
		||||
 | 
			
		||||
    @Parameterized.Parameter(1)
 | 
			
		||||
    public String input;
 | 
			
		||||
 | 
			
		||||
    @Parameterized.Parameter(2)
 | 
			
		||||
    public String output;
 | 
			
		||||
 | 
			
		||||
    @Parameterized.Parameter(3)
 | 
			
		||||
    public String trimOutput;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void match() {
 | 
			
		||||
        JLatexMathInlineProcessor processor = new JLatexMathInlineProcessor(allowSingle$);
 | 
			
		||||
        Matcher matcher = processor.pattern.matcher(input);
 | 
			
		||||
        if (output == null || "".equals(output)) {
 | 
			
		||||
            Assert.assertFalse(matcher.find());
 | 
			
		||||
        } else {
 | 
			
		||||
            Assert.assertTrue(matcher.find());
 | 
			
		||||
            String actual = matcher.group();
 | 
			
		||||
            Assert.assertEquals(output, actual);
 | 
			
		||||
            Assert.assertEquals(trimOutput, processor.trimDollar(actual));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void not_match() {
 | 
			
		||||
        String[][] testCase = new String[][]{
 | 
			
		||||
            new String[]{"lllll bbb xxx dhaksdhk\n asd ${b}"},
 | 
			
		||||
            new String[]{"asdhfalkhasl suaflhslia lasdjikaih sahk"},
 | 
			
		||||
            new String[]{"lllll bbb $xxx dhaksdhk\n asd"},
 | 
			
		||||
        };
 | 
			
		||||
        for (String[] c : testCase) {
 | 
			
		||||
            String input = c[0];
 | 
			
		||||
            JLatexMathInlineProcessor processor = new JLatexMathInlineProcessor(true);
 | 
			
		||||
            Matcher matcher = processor.pattern.matcher(input);
 | 
			
		||||
            Assert.assertFalse(matcher.find());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user