org.pegdown.ParserWithDirectives Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of paradox_2.10 Show documentation
Show all versions of paradox_2.10 Show documentation
Paradox is a markdown documentation tool for software projects.
The newest version!
/*
* Copyright © 2015 - 2019 Lightbend, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pegdown;
import org.parboiled.Context;
import org.parboiled.Rule;
import org.parboiled.support.StringBuilderVar;
import org.parboiled.support.Var;
import org.pegdown.ast.*;
import org.pegdown.plugins.PegDownPlugins;
import java.util.List;
/**
* Markdown parser that includes general markdown directives.
*
* Based on http://talk.commonmark.org/t/generic-directives-plugins-syntax
*/
public class ParserWithDirectives extends Parser {
public static char DIRECTIVE_MARKER = '@';
public static char VAR_SUBSTITUTION_MARKER = '$';
public ParserWithDirectives(Integer options, Long maxParsingTimeInMillis, Parser.ParseRunnerProvider parseRunnerProvider, PegDownPlugins plugins) {
super(options, maxParsingTimeInMillis, parseRunnerProvider, plugins);
}
// Add directive rules into parser
// Added like this, rather than plugins, for recursive parsing
@Override
public Rule NonLinkInline() {
Rule nonLinkInline = super.NonLinkInline();
return FirstOf(EscapedVarSubstitutionStart(), VarSubstitution(), InlineDirective(), nonLinkInline);
}
@Override
public Rule Block() {
Rule block = super.Block();
return Sequence(
ZeroOrMore(BlankLine()),
FirstOf(BlockDirective(), block)
);
}
// var substitution
public Rule EscapedVarSubstitutionStart() {
return Sequence('\\', VAR_SUBSTITUTION_MARKER, push(new SpecialTextNode(match())));
}
public Rule VarSubstitution() {
return Sequence(
VAR_SUBSTITUTION_MARKER,
VarName(),
VAR_SUBSTITUTION_MARKER,
push(new DirectiveNode(DirectiveNode.Format.Inline, "var", popAsString(),
DirectiveNode.Source.Empty, new DirectiveAttributes.AttributeMap(), new SuperNode()))
);
}
public Rule VarName() {
StringBuilderVar name = new StringBuilderVar();
return Sequence(
name.clearContents(),
Letter(), name.append(matchedChar()),
ZeroOrMore(
FirstOf(
Sequence(FirstOf(Alphanumeric(), AnyOf("+-_.")), name.append(matchedChar())),
Sequence('\\', VAR_SUBSTITUTION_MARKER, name.append(VAR_SUBSTITUTION_MARKER))
)
),
push(name.getString())
);
}
// Inline directive
public Rule InlineDirective() {
return NodeSequence(
DIRECTIVE_MARKER,
DirectiveName(),
DirectiveLabel(),
DirectiveSource(),
MaybeDirectiveAttributes(),
push(inlineDirectiveNode())
);
}
public Node inlineDirectiveNode() {
DirectiveAttributes attributes = (DirectiveAttributes) pop();
DirectiveNode.Source source = (DirectiveNode.Source) pop();
Node labelChild = popAsNode();
String label = extractLabelText(labelChild);
String name = popAsString();
return new DirectiveNode(DirectiveNode.Format.Inline, name, label, source, attributes, labelChild);
}
public String extractLabelText(Node node) {
return getContext().getInputBuffer().extract(node.getStartIndex() + 1, node.getEndIndex() - 1);
}
// Block directives
public Rule BlockDirective() {
return FirstOf(LeafBlockDirective(), ContainerBlockDirective());
}
// Leaf block directive
public Rule LeafBlockDirective() {
return NodeSequence(
DIRECTIVE_MARKER, DIRECTIVE_MARKER, Sp(),
DirectiveName(),
MaybeDirectiveLabel(),
DirectiveSource(),
MaybeDirectiveAttributes(), Sp(), Newline(),
push(leafBlockDirectiveNode())
);
}
public Node leafBlockDirectiveNode() {
DirectiveAttributes attributes = (DirectiveAttributes) pop();
DirectiveNode.Source source = (DirectiveNode.Source) pop();
Node labelChild = popAsNode();
String label = extractLabelText(labelChild);
String name = popAsString();
return new DirectiveNode(DirectiveNode.Format.LeafBlock, name, label, source, attributes, labelChild);
}
// Container block directive
public Rule ContainerBlockDirective() {
Var markerLength = new Var();
return NodeSequence(
ContainerBlockDirectiveStart(markerLength),
ContainerBlockDirectiveContents(markerLength),
ContainerBlockDirectiveEnd(markerLength),
push(containerBlockDirectiveNode())
);
}
public Rule ContainerBlockDirectiveStart(Var markerLength) {
return Sequence(
markerLength.clear(),
ContainerBlockMarker(markerLength), Sp(),
DirectiveName(),
MaybeDirectiveTextLabel(),
DirectiveSource(),
MaybeDirectiveAttributes(), Sp(), Newline()
);
}
public Rule ContainerBlockMarker(Var markerLength) {
return Sequence(
NOrMore(DIRECTIVE_MARKER, 3),
(markerLength.isSet() && matchLength() == markerLength.get()) ||
(markerLength.isNotSet() && markerLength.set(matchLength()))
);
}
public Rule ContainerBlockDirectiveContents(Var markerLength) {
StringBuilderVar contents = new StringBuilderVar();
return Sequence(
push(getContext().getCurrentIndex()),
contents.clearContents(),
OneOrMore(TestNot(ContainerBlockDirectiveEnd(markerLength)), ANY, contents.append(matchedChar())),
push(parseBlockContents(markerLength, contents.appended("\n\n")))
);
}
public Node parseBlockContents(Var markerLength, StringBuilderVar block) {
// recursively parse inner contents
Context
© 2015 - 2024 Weber Informatics LLC | Privacy Policy