pegdown icon indicating copy to clipboard operation
pegdown copied to clipboard

Block and inline parser plugins can't be used together

Open aadamovich opened this issue 12 years ago • 0 comments

I have the following plugin. It gives additional inline styling for keywords, screen texts and shortcuts, as well as detects TODOs and allows defining special blocks called info boxes:

package org.pegdown;

import org.parboiled.BaseParser;
import org.parboiled.Rule;
import org.parboiled.support.StringBuilderVar;
import org.pegdown.plugins.BlockPluginParser;
import org.pegdown.plugins.InlinePluginParser;

import com.aestasit.docx.packt.nodes.InfoBoxNode;
import com.aestasit.docx.packt.nodes.KeywordNode;
import com.aestasit.docx.packt.nodes.ScreenTextNode;
import com.aestasit.docx.packt.nodes.ShortcutNode;
import com.aestasit.docx.packt.nodes.TodoNode;

public class CookbookNodeParser extends Parser implements InlinePluginParser, BlockPluginParser {

  protected static final char CROSSED_OUT = '\uffff';

  public CookbookNodeParser() {
    super(ALL, 1000l, DefaultParseRunnerProvider);
  }

  @Override
  public Rule[] inlinePluginRules() {
    return new Rule[] { Todo(), Shortcut(), ScreenText(), Keyword() };
  }

  @Override
  public Rule[] blockPluginRules() {
    return new Rule[] { InfoBox() };
  }

  public Rule Todo() {
    final StringBuilderVar text = new StringBuilderVar();
    final StringBuilderVar type = new StringBuilderVar();
    return NodeSequence(
      Ch('%'),
      Optional(Ch('X'), type.append(matchedChar())),
      String("TODO"),
      Optional(Ch(':')),
      OneOrMore(TestNot(Ch('%')), BaseParser.ANY, text.append(matchedChar())),
      push(new TodoNode(text.getString().trim(), "X".equals(type.getString()))),
      Ch('%')    
    );
  }

  public Rule Shortcut() {
    final StringBuilderVar text = new StringBuilderVar();
    return NodeSequence(
      String("~"),
      OneOrMore(TestNot(AnyOf("~ \t\f")), BaseParser.ANY, text.append(matchedChar())),
      push(new ShortcutNode(text.getString())),
      String("~")
    );
  }

  public Rule Keyword() {
    final StringBuilderVar text = new StringBuilderVar();
    return NodeSequence(
      String("{"),
      OneOrMore(TestNot(Ch('}')), BaseParser.ANY, text.append(matchedChar())),
      push(new KeywordNode(text.getString())),
      String("}")    
    );
  }

  public Rule ScreenText() {
    final StringBuilderVar text = new StringBuilderVar();
    return NodeSequence(
       String("\"`"),
       OneOrMore(TestNot(Ch('`')), BaseParser.ANY, text.append(matchedChar())),
       push(new ScreenTextNode(text.getString())),
       String("`\"")
     );
  }

  public Rule InfoBox() {
    StringBuilderVar inner = new StringBuilderVar();
    return NodeSequence(
       OneOrMore(
       CrossedOut(Sequence('|', Optional(' ')), inner),
       Line(inner),
       ZeroOrMore(TestNot('|'), TestNot(BlankLine()), Line(inner)),
       ZeroOrMore(BlankLine(), inner.append(match()))),
       push(new InfoBoxNode(withIndicesShifted(parseInternal(inner), (Integer) peek()).getChildren())));
  }

}

The problem is that when I insert keyword style (or any other non-standard inline style) inside info box block, pegdown does not recognize those. Curly brackets used for keywords are just parsed as special text, not as KeywordNode. Is there any error in my parsing logic?

aadamovich avatar Nov 11 '13 10:11 aadamovich