diff --git a/doxia-core/pom.xml b/doxia-core/pom.xml
index 449f43398..a240a790a 100644
--- a/doxia-core/pom.xml
+++ b/doxia-core/pom.xml
@@ -25,7 +25,7 @@ under the License.
...
-assert content =~ 'inline code: System.out.println'
-
-// The last one is inline "fenced" code block which must be in simple
-assert content =~ 'And what about System.out.println'
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/pom.xml b/doxia-modules/doxia-module-markdown/src/it/general/pom.xml
deleted file mode 100644
index 12afb4fdb..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/pom.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
- 4.0.0
-
- org.apache.maven.doxia
- it
- 1.0-SNAPSHOT
- pom
-
- Project Description
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-site-plugin
- 3.9.1
-
- false
- false
- UTF-8
- UTF-8
-
-
-
- org.apache.maven.doxia
- doxia-core
- @project.version@
-
-
- org.apache.maven.doxia
- doxia-module-xhtml
- @project.version@
-
-
- @project.groupId@
- @project.artifactId@
- @project.version@
-
-
-
-
-
-
-
-
-
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/index.md b/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/index.md
deleted file mode 100644
index f509994c1..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/index.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# General Integration Tests for Doxia Markdown Module
-
-Each page is dedicated to one specific feature of the Doxia Markdown Module.
-
-Everything is tested in **verify.groovy**.
\ No newline at end of file
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/metadata.md b/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/metadata.md
deleted file mode 100644
index de13a2758..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/metadata.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Author: Bertrand 'Yours, Truly' Martin
-Title: Title from Header
-Keywords: smile,😉,utf-8
-Empty:
-
- Weird : Spacing
-
-
-# Title from Title
-
-description: This description must not be included in the header
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/quotes.md b/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/quotes.md
deleted file mode 100644
index a92205502..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/src/site/markdown/quotes.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Quotes
-
-This ain't a quote, but an apostrophe.
-
-This 'quoted text' isn't surrounded with apostrophes.
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/src/site/site.xml b/doxia-modules/doxia-module-markdown/src/it/general/src/site/site.xml
deleted file mode 100644
index 7bbac30a2..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/src/site/site.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doxia-modules/doxia-module-markdown/src/it/general/verify.groovy b/doxia-modules/doxia-module-markdown/src/it/general/verify.groovy
deleted file mode 100644
index a6199f48a..000000000
--- a/doxia-modules/doxia-module-markdown/src/it/general/verify.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-// Verify index.html
-
-// File was produced
-File resultFile = new File(basedir, "target/site/index.html")
-assert resultFile.isFile()
-
-
-// Verify metadata.html
-
-// File was produced
-resultFile = new File(basedir, "target/site/metadata.html")
-assert resultFile.isFile()
-
-// Check the content
-String content = resultFile.text;
-
-// must contain the specified title in the metadata, not in the first heading
-assert content =~ '.*Title from Header.* '
-
-// Author is Bertrand, yours truly
-// Apostrophe must have been interpreted properly
-assert content =~ ''
-
-// Keywords do support utf-8 smileys
-assert content =~ ''
-
-// Meta are properly trimmed
-assert content =~ ''
-
-// Empty is empty
-assert content =~ ''
-
-// No description is provided, as it was not part of the metadata at the beginning of the doc
-assert !(content =~ '
-
-
-
-
-
-
- it-repo
-
- true
-
-
-
- 1local.central
- @localRepositoryUrl@
-
- true
-
-
- true
-
-
-
-
-
- 1local.central
- @localRepositoryUrl@
-
- true
-
-
- true
-
-
-
-
-
-
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaExtension.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaExtension.java
new file mode 100644
index 000000000..f020d45df
--- /dev/null
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaExtension.java
@@ -0,0 +1,58 @@
+package org.apache.maven.doxia.module.markdown;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import com.vladsch.flexmark.html.HtmlRenderer;
+import com.vladsch.flexmark.util.builder.Extension;
+import com.vladsch.flexmark.util.options.DataKey;
+import com.vladsch.flexmark.util.options.MutableDataHolder;
+
+/**
+ * Implements flexmark-java extension to render fenced code and indented code using doxia format
+ */
+class FlexmarkDoxiaExtension implements HtmlRenderer.HtmlRendererExtension
+{
+ /** Constant INPUT_FILE_EXTENSION
*/
+ public static final DataKey INPUT_FILE_EXTENSION = new DataKey<>( "INPUT_FILE_EXTENSION", "md" );
+
+ /** {@inheritDoc} */
+ @Override
+ public void rendererOptions( final MutableDataHolder options )
+ {
+
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void extend( HtmlRenderer.Builder rendererBuilder, String rendererType )
+ {
+ rendererBuilder.nodeRendererFactory( new FlexmarkDoxiaNodeRenderer.Factory() );
+ }
+
+ /**
+ * create.
+ *
+ * @return a {@link com.vladsch.flexmark.util.builder.Extension} object.
+ */
+ public static Extension create()
+ {
+ return new FlexmarkDoxiaExtension();
+ }
+}
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaNodeRenderer.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaNodeRenderer.java
new file mode 100644
index 000000000..dadf24b5b
--- /dev/null
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaNodeRenderer.java
@@ -0,0 +1,146 @@
+package org.apache.maven.doxia.module.markdown;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import com.vladsch.flexmark.ast.FencedCodeBlock;
+import com.vladsch.flexmark.ast.IndentedCodeBlock;
+import com.vladsch.flexmark.html.CustomNodeRenderer;
+import com.vladsch.flexmark.html.HtmlWriter;
+import com.vladsch.flexmark.html.renderer.NodeRenderer;
+import com.vladsch.flexmark.html.renderer.NodeRendererContext;
+import com.vladsch.flexmark.html.renderer.NodeRendererFactory;
+import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
+import com.vladsch.flexmark.util.options.DataHolder;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The node renderer that renders all the core nodes (comes last in the order of node renderers).
+ */
+@SuppressWarnings( "WeakerAccess" )
+class FlexmarkDoxiaNodeRenderer implements NodeRenderer
+{
+ FlexmarkDoxiaNodeRenderer( DataHolder options )
+ {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Set> getNodeRenderingHandlers()
+ {
+ return new HashSet>( Arrays.asList(
+ new NodeRenderingHandler<>( IndentedCodeBlock.class, new CustomNodeRenderer()
+ {
+ @Override
+ public void render( IndentedCodeBlock node, NodeRendererContext context, HtmlWriter html )
+ {
+ FlexmarkDoxiaNodeRenderer.this.render( node, context, html );
+ }
+ } ),
+ new NodeRenderingHandler<>( FencedCodeBlock.class, new CustomNodeRenderer()
+ {
+ @Override
+ public void render( FencedCodeBlock node, NodeRendererContext context, HtmlWriter html )
+ {
+ FlexmarkDoxiaNodeRenderer.this.render( node, context, html );
+ }
+ } )
+ ) );
+ }
+
+ private void render( IndentedCodeBlock node, NodeRendererContext context, HtmlWriter html )
+ {
+ html.line();
+ html.attr( "class", "source" ).withAttr().tag( "div" );
+ html.srcPosWithEOL( node.getChars() ).tag( "pre" ).openPre();
+
+ String noLanguageClass = context.getHtmlOptions().noLanguageClass.trim();
+ if ( !noLanguageClass.isEmpty() )
+ {
+ html.attr( "class", noLanguageClass );
+ }
+
+ //html.srcPosWithEOL(node.getContentChars()).withAttr(CoreNodeRenderer.CODE_CONTENT).tag("code");
+ String s = node.getContentChars().trimTailBlankLines().normalizeEndWithEOL();
+ while ( !s.isEmpty() && s.charAt( 0 ) == '\n' )
+ {
+ html.raw( "
" );
+ s = s.substring( 1 );
+ }
+ html.text( s );
+
+ //html.tag("/code");
+ html.tag( "/pre" ).closePre();
+ html.tag( "/div" );
+ html.line();
+ }
+
+ private void render( FencedCodeBlock node, NodeRendererContext context, HtmlWriter html )
+ {
+ html.line();
+ html.attr( "class", "source" ).withAttr().tag( "div" );
+ html.srcPosWithTrailingEOL( node.getChars() ).tag( "pre" ).openPre();
+
+ //BasedSequence info = node.getInfo();
+ //if (info.isNotNull() && !info.isBlank()) {
+ // int space = info.indexOf(' ');
+ // BasedSequence language;
+ // if (space == -1) {
+ // language = info;
+ // } else {
+ // language = info.subSequence(0, space);
+ // }
+ // html.attr("class", context.getHtmlOptions().languageClassPrefix + language.unescape());
+ //} else {
+ // String noLanguageClass = context.getHtmlOptions().noLanguageClass.trim();
+ // if (!noLanguageClass.isEmpty()) {
+ // html.attr("class", noLanguageClass);
+ // }
+ //}
+
+ //html.srcPosWithEOL(node.getContentChars()).withAttr(CoreNodeRenderer.CODE_CONTENT).tag("code");
+ String s = node.getContentChars().normalizeEOL();
+ while ( !s.isEmpty() && s.charAt( 0 ) == '\n' )
+ {
+ html.raw( "
" );
+ s = s.substring( 1 );
+ }
+ html.text( s );
+
+ //html.tag("/code");
+ html.tag( "/pre" ).closePre();
+ html.tag( "/div" );
+ html.line();
+ }
+
+ /**
+ * Factory for doxia node renderer
+ */
+ public static class Factory implements NodeRendererFactory
+ {
+ @Override
+ public NodeRenderer create( final DataHolder options )
+ {
+ return new FlexmarkDoxiaNodeRenderer( options );
+ }
+ }
+}
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
index 971c35f86..f40e123c5 100644
--- a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
@@ -24,24 +24,18 @@
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.ast.util.TextCollectingVisitor;
import com.vladsch.flexmark.html.HtmlRenderer;
-import com.vladsch.flexmark.util.options.MutableDataSet;
-import com.vladsch.flexmark.ext.escaped.character.EscapedCharacterExtension;
-import com.vladsch.flexmark.ext.abbreviation.AbbreviationExtension;
-import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
-import com.vladsch.flexmark.ext.definition.DefinitionExtension;
-import com.vladsch.flexmark.ext.typographic.TypographicExtension;
-import com.vladsch.flexmark.ext.tables.TablesExtension;
-import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension;
-import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
-
-import org.apache.commons.io.input.CharSequenceReader;
+import com.vladsch.flexmark.profiles.pegdown.Extensions;
+import com.vladsch.flexmark.profiles.pegdown.PegdownOptionsAdapter;
+import com.vladsch.flexmark.util.builder.Extension;
+import com.vladsch.flexmark.util.options.MutableDataHolder;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.maven.doxia.markup.HtmlMarkup;
import org.apache.maven.doxia.module.xhtml.XhtmlParser;
import org.apache.maven.doxia.parser.AbstractParser;
import org.apache.maven.doxia.parser.ParseException;
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.sink.Sink;
-import org.apache.maven.doxia.util.HtmlTools;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.IOUtil;
@@ -49,7 +43,8 @@
import java.io.IOException;
import java.io.Reader;
-import java.util.Arrays;
+import java.io.StringReader;
+import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -79,100 +74,48 @@ public class MarkdownParser
/**
* Regex that identifies a multimarkdown-style metadata section at the start of the document
- *
- * In order to ensure that we have minimal risk of false positives when slurping metadata sections, the
- * first key in the metadata section must be one of these standard keys or else the entire metadata section is
- * ignored.
*/
- private static final Pattern METADATA_SECTION_PATTERN = Pattern.compile(
- "\\A^\\s*"
- + "(?:title|author|date|address|affiliation|copyright|email|keywords|language|phone|subtitle)"
- + "\\h*:\\h*\\V*\\h*$\\v+"
- + "(?:^\\h*[^:\\v]+\\h*:\\h*\\V*\\h*$\\v+)*",
- Pattern.MULTILINE | Pattern.CASE_INSENSITIVE );
+ private static final String MULTI_MARKDOWN_METADATA_SECTION =
+ "^(((?:[^\\s:][^:]*):(?:.*(?:\r?\n\\p{Blank}+[^\\s].*)*\r?\n))+)(?:\\s*\r?\n)";
/**
* Regex that captures the key and value of a multimarkdown-style metadata entry.
*/
- private static final Pattern METADATA_ENTRY_PATTERN = Pattern.compile(
- "^\\h*([^:\\v]+?)\\h*:\\h*(\\V*)\\h*$",
- Pattern.MULTILINE );
+ private static final String MULTI_MARKDOWN_METADATA_ENTRY =
+ "([^\\s:][^:]*):(.*(?:\r?\n\\p{Blank}+[^\\s].*)*)\r?\n";
+
+ /**
+ * In order to ensure that we have minimal risk of false positives when slurping metadata sections, the
+ * first key in the metadata section must be one of these standard keys or else the entire metadata section is
+ * ignored.
+ */
+ private static final String[] STANDARD_METADATA_KEYS =
+ { "title", "author", "date", "address", "affiliation", "copyright", "email", "keywords", "language", "phone",
+ "subtitle" };
/**
* getType.
*
* @return a int.
*/
- @Override
public int getType()
{
return TXT_TYPE;
}
- /**
- * The parser of the HTML produced by Flexmark, that we will
- * use to convert this HTML to Sink events
- */
@Requirement
private MarkdownHtmlParser parser;
- /**
- * Flexmark's Markdown parser (one static instance fits all)
- */
- private static final com.vladsch.flexmark.parser.Parser FLEXMARK_PARSER;
-
- /**
- * Flexmark's HTML renderer (its output will be re-parsed and converted to Sink events)
- */
- private static final HtmlRenderer FLEXMARK_HTML_RENDERER;
-
- // Initialize the Flexmark parser and renderer, once and for all
- static
- {
- MutableDataSet flexmarkOptions = new MutableDataSet();
-
- // Enable the extensions that we used to have in Pegdown
- flexmarkOptions.set( com.vladsch.flexmark.parser.Parser.EXTENSIONS, Arrays.asList(
- EscapedCharacterExtension.create(),
- AbbreviationExtension.create(),
- AutolinkExtension.create(),
- DefinitionExtension.create(),
- TypographicExtension.create(),
- TablesExtension.create(),
- WikiLinkExtension.create(),
- StrikethroughExtension.create()
- ) );
-
- // Disable wrong apostrophe replacement
- flexmarkOptions.set( TypographicExtension.SINGLE_QUOTE_UNMATCHED, "'" );
-
- // Additional options on the HTML rendering
- flexmarkOptions.set( HtmlRenderer.HTML_BLOCK_OPEN_TAG_EOL, false );
- flexmarkOptions.set( HtmlRenderer.HTML_BLOCK_CLOSE_TAG_EOL, false );
- flexmarkOptions.set( HtmlRenderer.MAX_TRAILING_BLANK_LINES, -1 );
-
- // Build the Markdown parser
- FLEXMARK_PARSER = com.vladsch.flexmark.parser.Parser.builder( flexmarkOptions ).build();
-
- // Build the HTML renderer
- FLEXMARK_HTML_RENDERER = HtmlRenderer.builder( flexmarkOptions )
- .linkResolverFactory( new FlexmarkDoxiaLinkResolver.Factory() )
- .build();
-
- }
-
/** {@inheritDoc} */
- @Override
public void parse( Reader source, Sink sink )
throws ParseException
{
try
{
// Markdown to HTML (using flexmark-java library)
- CharSequence html = toHtml( source );
-
+ String html = toHtml( source );
// then HTML to Sink API
- parser.parse( new CharSequenceReader( html ), sink );
+ parser.parse( new StringReader( html ), sink );
}
catch ( IOException e )
{
@@ -187,98 +130,133 @@ public void parse( Reader source, Sink sink )
* @return HTML content generated by flexmark-java
* @throws IOException passed through
*/
- CharSequence toHtml( Reader source )
+ String toHtml( Reader source )
throws IOException
{
- // Read the source
String text = IOUtil.toString( source );
+ MutableDataHolder flexmarkOptions = PegdownOptionsAdapter.flexmarkOptions(
+ Extensions.ALL & ~( Extensions.HARDWRAPS | Extensions.ANCHORLINKS ) ).toMutable();
+ ArrayList extensions = new ArrayList<>();
+ for ( Extension extension : flexmarkOptions.get( com.vladsch.flexmark.parser.Parser.EXTENSIONS ) )
+ {
+ extensions.add( extension );
+ }
+
+ extensions.add( FlexmarkDoxiaExtension.create() );
+ flexmarkOptions.set( com.vladsch.flexmark.parser.Parser.EXTENSIONS, extensions );
+ flexmarkOptions.set( HtmlRenderer.HTML_BLOCK_OPEN_TAG_EOL, false );
+ flexmarkOptions.set( HtmlRenderer.HTML_BLOCK_CLOSE_TAG_EOL, false );
+ flexmarkOptions.set( HtmlRenderer.MAX_TRAILING_BLANK_LINES, -1 );
+
+ com.vladsch.flexmark.parser.Parser parser = com.vladsch.flexmark.parser.Parser.builder( flexmarkOptions )
+ .build();
+ HtmlRenderer renderer = HtmlRenderer.builder( flexmarkOptions )
+ .linkResolverFactory( new FlexmarkDoxiaLinkResolver.Factory() )
+ .build();
+
- // Now, build the HTML document
StringBuilder html = new StringBuilder( 1000 );
html.append( "" );
html.append( "" );
-
- // First, we interpret the "metadata" section of the document and add the corresponding HTML headers
- Matcher metadataMatcher = METADATA_SECTION_PATTERN.matcher( text );
+ Pattern metadataPattern = Pattern.compile( MULTI_MARKDOWN_METADATA_SECTION, Pattern.MULTILINE );
+ Matcher metadataMatcher = metadataPattern.matcher( text );
boolean haveTitle = false;
if ( metadataMatcher.find() )
{
- Matcher entryMatcher = METADATA_ENTRY_PATTERN.matcher( metadataMatcher.group( 0 ) );
- while ( entryMatcher.find() )
+ metadataPattern = Pattern.compile( MULTI_MARKDOWN_METADATA_ENTRY, Pattern.MULTILINE );
+ Matcher lineMatcher = metadataPattern.matcher( metadataMatcher.group( 1 ) );
+ boolean first = true;
+ while ( lineMatcher.find() )
{
- String key = entryMatcher.group( 1 );
- String value = entryMatcher.group( 2 );
+ String key = StringUtils.trimToEmpty( lineMatcher.group( 1 ) );
+ if ( first )
+ {
+ boolean found = false;
+ for ( String k : STANDARD_METADATA_KEYS )
+ {
+ if ( k.equalsIgnoreCase( key ) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ break;
+ }
+ first = false;
+ }
+ String value = StringUtils.trimToEmpty( lineMatcher.group( 2 ) );
if ( "title".equalsIgnoreCase( key ) )
{
haveTitle = true;
html.append( "" );
- html.append( HtmlTools.escapeHTML( value, false ) );
+ html.append( StringEscapeUtils.escapeXml( value ) );
html.append( " " );
}
+ else if ( "author".equalsIgnoreCase( key ) )
+ {
+ html.append( "" );
+ }
+ else if ( "date".equalsIgnoreCase( key ) )
+ {
+ html.append( "" );
+ }
else
{
- html.append( "" );
+ html.append( "" );
}
}
-
- // Trim the metadata from the source
- text = text.substring( metadataMatcher.end( 0 ) );
-
+ if ( !first )
+ {
+ text = text.substring( metadataMatcher.end() );
+ }
}
- // Now is the time to parse the Markdown document
- // (after we've trimmed out the metadatas, and before we check for its headings)
- Node documentRoot = FLEXMARK_PARSER.parse( text );
+ Node rootNode = parser.parse( text );
+ String markdownHtml = renderer.render( rootNode );
- // Special trick: if there is no title specified as a metadata in the header, we will use the first
- // heading as the document title
- if ( !haveTitle && documentRoot.hasChildren() )
+ if ( !haveTitle && rootNode.hasChildren() )
{
- // Skip the comment nodes
- Node firstNode = documentRoot.getFirstChild();
- while ( firstNode != null && firstNode instanceof HtmlCommentBlock )
+ // use the first (non-comment) node only if it is a heading
+ Node firstNode = rootNode.getFirstChild();
+ while ( firstNode != null && !( firstNode instanceof Heading ) )
{
+ if ( !( firstNode instanceof HtmlCommentBlock ) )
+ {
+ break;
+ }
firstNode = firstNode.getNext();
}
- // If this first non-comment node is a heading, we use it as the document title
- if ( firstNode != null && firstNode instanceof Heading )
+ if ( firstNode instanceof Heading )
{
html.append( "" );
TextCollectingVisitor collectingVisitor = new TextCollectingVisitor();
String headingText = collectingVisitor.collectAndGetText( firstNode );
- html.append( HtmlTools.escapeHTML( headingText, false ) );
+ html.append( StringEscapeUtils.escapeXml( headingText ) );
html.append( " " );
}
}
html.append( "" );
html.append( "" );
-
- // Convert our Markdown document to HTML and append it to our HTML
- FLEXMARK_HTML_RENDERER.render( documentRoot, html );
-
+ html.append( markdownHtml );
html.append( "" );
html.append( "" );
- return html;
+ return html.toString();
}
/**
* Internal parser for HTML generated by the Markdown library.
- *
- * 2 special things:
- *
- * - DIV elements are translated as Unknown Sink events
- *
- PRE elements are all considered as boxed
- *
- * PRE elements need to be "boxed" because the XhtmlSink will surround the
- * corresponding verbatim() Sink event with a DIV element with class="source",
- * which is how most Maven Skin (incl. Fluido) recognize a block of code, which
- * needs to be highlighted accordingly.
*/
@Component( role = MarkdownHtmlParser.class )
public static class MarkdownHtmlParser
@@ -289,13 +267,6 @@ public MarkdownHtmlParser()
super();
}
- @Override
- protected void init()
- {
- super.init();
- super.boxed = true;
- }
-
@Override
protected boolean baseEndTag( XmlPullParser parser, Sink sink )
{
@@ -320,7 +291,6 @@ protected boolean baseStartTag( XmlPullParser parser, Sink sink )
if ( parser.getName().equals( HtmlMarkup.DIV.toString() ) )
{
handleUnknown( parser, sink, TAG_TYPE_START );
- super.boxed = true;
visited = true;
}
}
diff --git a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
index 1431bd675..8110378b7 100644
--- a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
+++ b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
@@ -165,42 +165,11 @@ public void testCodeSinkEvent()
{
Iterator it = parseFileToEventTestingSink( "code" ).getEventList().iterator();
- assertEquals( it, "head", "head_", "body", "paragraph", "text", "paragraph_", "text", "verbatim", "inline", "text", "inline_", "verbatim_", "body_" );
+ assertEquals( it, "head", "head_", "body", "paragraph", "text", "paragraph_", "text", "unknown", "verbatim", "text", "verbatim_", "unknown", "body_" );
assertFalse( it.hasNext() );
}
- /**
- * Assert the verbatim sink event is fired when parsing "fenced-code-block.md".
- *
- * @throws Exception if the event list is not correct when parsing the document
- */
- public void testFencedCodeBlockSinkEvent()
- throws Exception
- {
- List eventList = parseFileToEventTestingSink( "fenced-code-block" ).getEventList();
- Iterator it = eventList.iterator();
-
- assertEquals( it, "head", "head_", "body", "paragraph", "text", "paragraph_", "text", "verbatim", "inline", "text", "inline_", "verbatim_", "body_" );
-
- assertFalse( it.hasNext() );
-
- // PRE element must be a "verbatim" Sink event that specifies
- // BOXED = true
- SinkEventElement pre = eventList.get( 7 );
- assertEquals( "verbatim", pre.getName() );
- SinkEventAttributeSet preAtts = (SinkEventAttributeSet) pre.getArgs()[0];
- assertTrue( preAtts.containsAttribute( SinkEventAttributes.DECORATION, "boxed" ) );
-
- // * CODE element must be an "inline" Sink event that specifies:
- // * SEMANTICS = "code" and CLASS = "language-java"
- SinkEventElement code = eventList.get( 8 );
- assertEquals( "inline", code.getName() );
- SinkEventAttributeSet codeAtts = (SinkEventAttributeSet) code.getArgs()[0];
- assertTrue( codeAtts.containsAttribute( SinkEventAttributes.SEMANTICS, "code" ) );
- assertTrue( codeAtts.containsAttribute( SinkEventAttributes.CLASS, "language-java" ) );
- }
-
/**
* Assert the figureGraphics sink event is fired when parsing "image.md".
*
@@ -254,7 +223,7 @@ public void testLinkRewriteSinkEvent()
public void testLinkWithAnchorAndQuery() throws Exception
{
Iterator it = parseFileToEventTestingSink( "link_anchor_query" ).getEventList().iterator();
-
+
assertEquals( it, "head", "head_", "body", "paragraph", "link", "text", "link_", "paragraph_", "body_" );
assertFalse( it.hasNext() );
@@ -300,36 +269,14 @@ public void testNumberedListSinkEvent()
public void testMetadataSinkEvent()
throws Exception
{
- List eventList = parseFileToEventTestingSink( "metadata" ).getEventList();
- Iterator it = eventList.iterator();
+ Iterator it = parseFileToEventTestingSink( "metadata" ).getEventList().iterator();
- assertEquals( it, "head", "title", "text", "text", "text", "title_", "author", "text", "author_", "date", "text", "date_",
- "unknown", "head_", "body", "unknown", "text", "unknown", "paragraph", "text", "paragraph_", "section1",
+ assertEquals( it, "head", "title", "text", "title_", "author", "text", "author_", "date", "text", "date_",
+ "head_", "body", "unknown", "text", "unknown", "paragraph", "text", "paragraph_", "section1",
"sectionTitle1", "text", "sectionTitle1_", "paragraph", "text", "paragraph_", "section1_",
"body_" );
assertFalse( it.hasNext() );
-
- // Title must be "A Title & a Test"
- assertEquals( "A Title ", eventList.get( 2 ).getArgs()[0]);
- assertEquals( "&", eventList.get( 3 ).getArgs()[0]);
- assertEquals( " a 'Test'", eventList.get( 4 ).getArgs()[0]);
-
- // Author must be "Somebody "
- assertEquals( "Somebody 'Nickname' Great ", eventList.get( 7 ).getArgs()[0]);
-
- // Date must be "2013 © Copyleft"
- assertEquals( "2013 \u00A9 Copyleft", eventList.get( 10 ).getArgs()[0]);
-
- // * META element must be an "unknown" Sink event that specifies:
- // * name = "keywords" and content = "maven,doxia,markdown"
- SinkEventElement meta = eventList.get( 12 );
- assertEquals( "unknown", meta.getName() );
- assertEquals( "meta", meta.getArgs()[0] );
- SinkEventAttributeSet metaAtts = (SinkEventAttributeSet) meta.getArgs()[2];
- assertTrue( metaAtts.containsAttribute( SinkEventAttributes.NAME, "keywords" ) );
- assertTrue( metaAtts.containsAttribute( "content", "maven,doxia,markdown" ) );
-
}
/**
@@ -343,9 +290,8 @@ public void testFirstHeadingSinkEvent()
Iterator it = parseFileToEventTestingSink( "first-heading" ).getEventList().iterator();
// NOTE: H1 is rendered as "unknown" and H2 is "section1" (see DOXIA-203)
- assertEquals( it, "head", "title", "text", "title_", "head_", "body", "comment", "text",
- "section1", "sectionTitle1", "text", "sectionTitle1_", "paragraph", "text",
- "paragraph_", "section1_", "body_" );
+ assertEquals( it, "head", "title", "text", "title_", "head_", "body", "section1", "sectionTitle1", "text",
+ "sectionTitle1_", "paragraph", "text", "paragraph_", "section1_", "body_" );
assertFalse( it.hasNext() );
}
@@ -412,7 +358,7 @@ protected String parseFileToHtml( String file ) throws ParseException, IOExcepti
{
try ( Reader reader = getTestReader( file ) )
{
- return parser.toHtml( reader ).toString();
+ return parser.toHtml( reader );
}
}
@@ -473,27 +419,4 @@ public void testFlexIssue384()
{
parseFileToEventTestingSink( "flex-384" );
}
-
- // Apostrophe versus single quotes
- // Simple apostrophes (like in Sophie's Choice) must not be replaced with a single quote
- public void testQuoteVsApostrophe()
- throws Exception
- {
- List eventList = parseFileToEventTestingSink( "quote-vs-apostrophe" ).getEventList();
-
- StringBuilder content = new StringBuilder();
- for ( SinkEventElement element : eventList )
- {
- if ( "text".equals(element.getName()) )
- {
- content.append( element.getArgs()[0] );
- }
- }
- assertEquals(
- "This apostrophe isn't a quote."
- + "This \u2018quoted text\u2019 isn't surrounded by apostrophes.",
- content.toString() );
-
- }
-
}
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/fenced-code-block.md b/doxia-modules/doxia-module-markdown/src/test/resources/fenced-code-block.md
deleted file mode 100644
index d8df735bf..000000000
--- a/doxia-modules/doxia-module-markdown/src/test/resources/fenced-code-block.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Below code is Java:
-
-```java
-System.out.println(helloWorld);
-```
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/first-heading.md b/doxia-modules/doxia-module-markdown/src/test/resources/first-heading.md
index 108f19960..622fffecc 100644
--- a/doxia-modules/doxia-module-markdown/src/test/resources/first-heading.md
+++ b/doxia-modules/doxia-module-markdown/src/test/resources/first-heading.md
@@ -1,7 +1,7 @@
-
+
First heading
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/metadata.md b/doxia-modules/doxia-module-markdown/src/test/resources/metadata.md
index 97ce7f118..dac80093c 100644
--- a/doxia-modules/doxia-module-markdown/src/test/resources/metadata.md
+++ b/doxia-modules/doxia-module-markdown/src/test/resources/metadata.md
@@ -1,13 +1,10 @@
+title: A title
+author: Somebody
+date: 2013
-title: A Title & a 'Test'
-author: Somebody 'Nickname' Great
+# The document
-date: 2013 © Copyleft
-keywords: maven,doxia,markdown
-
-# The document with look-alike header
-
-copyright: none
+Some text
## A subheading
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/quote-vs-apostrophe.md b/doxia-modules/doxia-module-markdown/src/test/resources/quote-vs-apostrophe.md
deleted file mode 100644
index 085244fc7..000000000
--- a/doxia-modules/doxia-module-markdown/src/test/resources/quote-vs-apostrophe.md
+++ /dev/null
@@ -1,3 +0,0 @@
-This apostrophe isn't a quote.
-
-This 'quoted text' isn't surrounded by apostrophes.
\ No newline at end of file
diff --git a/doxia-modules/doxia-module-rtf/pom.xml b/doxia-modules/doxia-module-rtf/pom.xml
index facf00d44..2a30e2e7d 100644
--- a/doxia-modules/doxia-module-rtf/pom.xml
+++ b/doxia-modules/doxia-module-rtf/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia-modules
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-modules/doxia-module-twiki/pom.xml b/doxia-modules/doxia-module-twiki/pom.xml
index d85610a12..90972bfff 100644
--- a/doxia-modules/doxia-module-twiki/pom.xml
+++ b/doxia-modules/doxia-module-twiki/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia-modules
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-modules/doxia-module-xdoc/pom.xml b/doxia-modules/doxia-module-xdoc/pom.xml
index 7998ffaff..cf795d019 100644
--- a/doxia-modules/doxia-module-xdoc/pom.xml
+++ b/doxia-modules/doxia-module-xdoc/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia-modules
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-modules/doxia-module-xhtml/pom.xml b/doxia-modules/doxia-module-xhtml/pom.xml
index 9346526dd..60174a5ba 100644
--- a/doxia-modules/doxia-module-xhtml/pom.xml
+++ b/doxia-modules/doxia-module-xhtml/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia-modules
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java b/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
index 470fc2f99..00cfc8d9f 100644
--- a/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
+++ b/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
@@ -53,7 +53,7 @@ public class XhtmlParser
implements XhtmlMarkup
{
/** For boxed verbatim. */
- protected boolean boxed;
+ private boolean boxed;
/** Empty elements don't write a closing tag. */
private boolean isEmptyElement;
diff --git a/doxia-modules/doxia-module-xhtml5/pom.xml b/doxia-modules/doxia-module-xhtml5/pom.xml
index 80456236c..ff86bf953 100644
--- a/doxia-modules/doxia-module-xhtml5/pom.xml
+++ b/doxia-modules/doxia-module-xhtml5/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia-modules
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-modules/pom.xml b/doxia-modules/pom.xml
index 2947978be..e12b2b9bf 100644
--- a/doxia-modules/pom.xml
+++ b/doxia-modules/pom.xml
@@ -22,7 +22,7 @@ under the License.
doxia
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-sink-api/pom.xml b/doxia-sink-api/pom.xml
index 0c09e3584..9d84aff32 100644
--- a/doxia-sink-api/pom.xml
+++ b/doxia-sink-api/pom.xml
@@ -25,7 +25,7 @@ under the License.
doxia
org.apache.maven.doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/doxia-test-docs/pom.xml b/doxia-test-docs/pom.xml
index 7ee1601b0..0f4a436eb 100644
--- a/doxia-test-docs/pom.xml
+++ b/doxia-test-docs/pom.xml
@@ -25,7 +25,7 @@ under the License.
org.apache.maven.doxia
doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
../pom.xml
diff --git a/pom.xml b/pom.xml
index d54de476b..b634aa6a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@ under the License.
org.apache.maven.doxia
doxia
- 1.10-SNAPSHOT
+ 1.9.2-SNAPSHOT
pom
Doxia
@@ -207,14 +207,6 @@ under the License.
plexus-utils
3.3.0
-
-
-
- commons-io
- commons-io
- 2.6
-
-
@@ -270,7 +262,6 @@ under the License.
src/test/site/**/*.confluence
src/test/resources/**/*.twiki
src/test/resources/**/*.md
- src/it/**/site/**/*.md
@@ -326,13 +317,6 @@ under the License.
org/apache/maven/doxia/module/fml/FmlContentParser
org/apache/maven/doxia/module/xdoc/XdocParser
-
-
-
- 8001
- org/apache/maven/doxia/module/markdown/FlexmarkDoxiaNodeRenderer$Factory
-
-