blob: a8a282aa19f0d5f4a3e6888173fd3781c29e0e3d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2016 Stefan Seelmann and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Stefan Seelmann - initial API and implementation
* Max Rydahl Andersen - Bug 474084
* Patrik Suzzi <psuzzi@gmail.com> - Bug 481670, 474084
* Jeremie Bresson - Bug 488246
*******************************************************************************/
package org.eclipse.mylyn.wikitext.asciidoc;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import org.eclipse.mylyn.wikitext.asciidoc.internal.AsciiDocContentState;
import org.eclipse.mylyn.wikitext.asciidoc.internal.AsciiDocDocumentBuilder;
import org.eclipse.mylyn.wikitext.asciidoc.internal.AsciiDocIdGenerationStrategy;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.AttributeDefinitionBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.CodeBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.CommentBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.HeadingBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.HorizontalRuleBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.ListBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.ParagraphBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.PreformattedBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.PropertiesLineBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.TableBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.TitleLineBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.block.UnderlinedHeadingBlock;
import org.eclipse.mylyn.wikitext.asciidoc.internal.phrase.BackslashEscapePhraseModifier;
import org.eclipse.mylyn.wikitext.asciidoc.internal.phrase.CssClassPhraseModifier;
import org.eclipse.mylyn.wikitext.asciidoc.internal.phrase.SimplePhraseModifier;
import org.eclipse.mylyn.wikitext.asciidoc.internal.phrase.SimplePhraseModifier.Mode;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.AnchorLinkMacroReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.AnchorLinkReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.EmailLinkReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.ExplicitLinkReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.ImplicitFormattedLinkReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.ImplicitLinkReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.InlineAttributeReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.InlineCommentReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.InlineEscapedAttributeReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.InlineImageReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.PreserverHtmlEntityToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.XrefMacroReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.token.XrefReplacementToken;
import org.eclipse.mylyn.wikitext.asciidoc.internal.util.ReadAheadDispatcher;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.SpanType;
import org.eclipse.mylyn.wikitext.parser.markup.AbstractMarkupLanguage;
import org.eclipse.mylyn.wikitext.parser.markup.Block;
import org.eclipse.mylyn.wikitext.parser.markup.ContentState;
import org.eclipse.mylyn.wikitext.parser.markup.IdGenerationStrategy;
import org.eclipse.mylyn.wikitext.parser.markup.token.PatternLineBreakReplacementToken;
/**
* A markup language implementing Asciidoc syntax.
*
* @author Stefan Seelmann
* @author Max Rydahl Andersen
* @since 3.0
*/
public class AsciiDocLanguage extends AbstractMarkupLanguage {
public AsciiDocLanguage() {
setName("AsciiDoc"); //$NON-NLS-1$
}
@Override
protected ContentState createState() {
AsciiDocContentState state = new AsciiDocContentState();
putInitialAttributes(state);
if (configuration instanceof AsciiDocMarkupLanguageConfiguration) {
Map<String, String> initialAttributes = ((AsciiDocMarkupLanguageConfiguration) configuration)
.getInitialAttributes();
if (initialAttributes != null) {
for (Map.Entry<String, String> e : initialAttributes.entrySet()) {
state.putAttribute(e.getKey(), e.getValue());
}
}
}
return state;
}
private void putInitialAttributes(AsciiDocContentState state) {
state.putAttribute(AsciiDocContentState.ATTRIBUTE_IDPREFIX, AsciiDocContentState.IDPREFIX_DEFAULT_VALUE);
state.putAttribute(AsciiDocContentState.ATTRIBUTE_IDSEPARATOR, AsciiDocContentState.IDSEPARATOR_DEFAULT_VALUE);
state.putAttribute(AsciiDocContentState.ATTRIBUTE_IMAGESDIR, ""); //$NON-NLS-1$
}
@Override
public IdGenerationStrategy getIdGenerationStrategy() {
return new AsciiDocIdGenerationStrategy();
}
@Override
protected void addStandardTokens(PatternBasedSyntax tokenSyntax) {
// HTML entities are preserved
tokenSyntax.add(new PreserverHtmlEntityToken());
// line ending with a + will cause a line Break
tokenSyntax.add(new PatternLineBreakReplacementToken("(\\s\\+)\\s*$")); //$NON-NLS-1$
}
@Override
protected void addStandardPhraseModifiers(PatternBasedSyntax phraseModifierSyntax) {
// attribute
phraseModifierSyntax.add(new InlineAttributeReplacementToken());
phraseModifierSyntax.add(new InlineEscapedAttributeReplacementToken());
// comments
phraseModifierSyntax.add(new InlineCommentReplacementToken());
// links
phraseModifierSyntax.add(new EmailLinkReplacementToken());
phraseModifierSyntax.add(new ExplicitLinkReplacementToken());
phraseModifierSyntax.add(new ImplicitFormattedLinkReplacementToken());
phraseModifierSyntax.add(new ImplicitLinkReplacementToken());
phraseModifierSyntax.add(new AnchorLinkReplacementToken());
phraseModifierSyntax.add(new AnchorLinkMacroReplacementToken());
phraseModifierSyntax.add(new XrefReplacementToken());
phraseModifierSyntax.add(new XrefMacroReplacementToken());
// backslash escaped span elements
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("++")); //$NON-NLS-1$
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("**")); //$NON-NLS-1$
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("__")); //$NON-NLS-1$
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("+")); //$NON-NLS-1$
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("*")); //$NON-NLS-1$
phraseModifierSyntax.add(new BackslashEscapePhraseModifier("_")); //$NON-NLS-1$
phraseModifierSyntax.add(new InlineImageReplacementToken());
// pass-through
phraseModifierSyntax.add(new SimplePhraseModifier("+++", SpanType.SPAN, Mode.SPECIAL));
// emphasis span elements
phraseModifierSyntax.add(new SimplePhraseModifier("``", SpanType.CODE, Mode.NESTING)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("++", SpanType.SPAN, Mode.NORMAL)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("**", SpanType.STRONG, Mode.NESTING)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("__", SpanType.EMPHASIS, Mode.NESTING)); //$NON-NLS-1$
// emphasis span elements on word boundaries
phraseModifierSyntax.beginGroup("(?:(?<=\\W)|^)(?:", 0);
phraseModifierSyntax.add(new SimplePhraseModifier("*", SpanType.STRONG, Mode.NESTING)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("_", SpanType.EMPHASIS, Mode.NESTING)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("`", SpanType.CODE, Mode.NESTING)); //$NON-NLS-1$
phraseModifierSyntax.add(new SimplePhraseModifier("+", SpanType.SPAN, Mode.NORMAL)); //$NON-NLS-1$
phraseModifierSyntax.add(new CssClassPhraseModifier());
phraseModifierSyntax.endGroup(")(?:(?=\\W)|$)", 0);
phraseModifierSyntax.add(new SimplePhraseModifier("^", SpanType.SUPERSCRIPT, Mode.NESTING));
phraseModifierSyntax.add(new SimplePhraseModifier("~", SpanType.SUBSCRIPT, Mode.NESTING));
}
@Override
protected void addStandardBlocks(List<Block> blocks, List<Block> paragraphBreakingBlocks) {
ListBlock listBlock = new ListBlock();
blocks.add(listBlock);
paragraphBreakingBlocks.add(listBlock);
AttributeDefinitionBlock attributeDefinition = new AttributeDefinitionBlock();
TitleLineBlock titleLineBlock = new TitleLineBlock();
PropertiesLineBlock propertiesLineBlock = new PropertiesLineBlock();
TableBlock tableBlock = new TableBlock();
PreformattedBlock preformattedBlock = new PreformattedBlock();
CommentBlock commentBlock = new CommentBlock();
HeadingBlock headingBlock = new HeadingBlock();
CodeBlock codeBlock = new CodeBlock();
HorizontalRuleBlock hrBlock = new HorizontalRuleBlock();
blocks.add(attributeDefinition);
blocks.add(titleLineBlock);
blocks.add(propertiesLineBlock);
blocks.add(tableBlock);
blocks.add(preformattedBlock);
blocks.add(headingBlock);
blocks.add(codeBlock);
blocks.add(commentBlock);
blocks.add(hrBlock);
paragraphBreakingBlocks.add(codeBlock);
paragraphBreakingBlocks.add(commentBlock);
paragraphBreakingBlocks.add(preformattedBlock);
}
@Override
protected Block createParagraphBlock() {
ParagraphBlock paragraphBlock = new ParagraphBlock();
UnderlinedHeadingBlock headingBlock = new UnderlinedHeadingBlock();
ReadAheadDispatcher readAheadBlock = new ReadAheadDispatcher(headingBlock, paragraphBlock);
return readAheadBlock;
}
@Override
public DocumentBuilder createDocumentBuilder(Writer out, boolean formatting) {
return new AsciiDocDocumentBuilder(out);
}
}