diff --git a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
index 87658e824..5e5cc0c24 100644
--- a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
+++ b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
@@ -471,7 +471,7 @@ public void content() {
/**
* Checks that the sequence [footer(), footer_()],
* invoked on the current sink, produces the same result as
- * {@link #getHeaderBlock getHeaderBlock()}.
+ * {@link #getFooterBlock()}.
*/
@Test
public void footer() {
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
index 1464343c6..e40d59dd8 100644
--- a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
@@ -18,8 +18,6 @@
*/
package org.apache.maven.doxia.module.markdown;
-import javax.swing.text.MutableAttributeSet;
-
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
@@ -34,12 +32,9 @@
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkEventAttributes;
-import org.apache.maven.doxia.sink.impl.AbstractTextSink;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
-import org.apache.maven.doxia.sink.impl.SinkUtils;
import org.apache.maven.doxia.sink.impl.Xhtml5BaseSink;
import org.apache.maven.doxia.util.DoxiaStringUtils;
-import org.apache.maven.doxia.util.DoxiaUtils;
import org.apache.maven.doxia.util.HtmlTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,8 +43,9 @@
* Markdown generator implementation.
*
* Note: The encoding used is UTF-8.
+ * Extends the Xhtml5 sink as in some context HTML needs to be emitted.
*/
-public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
+public class MarkdownSink extends Xhtml5BaseSink implements MarkdownMarkup {
private static final Logger LOGGER = LoggerFactory.getLogger(MarkdownSink.class);
// ----------------------------------------------------------------------
@@ -93,10 +89,10 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
private final LastTwoLinesBufferingWriter bufferingWriter;
/** Keep track of end markup for inline events. */
- protected Queue> inlineStack = Collections.asLifoQueue(new LinkedList<>());
+ protected Queue> inlineStack;
/** The context of the surrounding elements as stack (LIFO) */
- protected Queue elementContextStack = Collections.asLifoQueue(new LinkedList<>());
+ protected Queue elementContextStack;
private String figureSrc;
@@ -220,6 +216,13 @@ boolean isBlock() {
return type == Type.CONTAINER_BLOCK || type == Type.LEAF_BLOCK;
}
+ /**
+ *
+ * @return {@code true} if only HTML is allowed in this context
+ */
+ boolean isHtml() {
+ return this.equals(HTML_BLOCK);
+ }
/**
*
* @return {@code true} for all containers (allowing block elements as children), {@code false} otherwise
@@ -332,14 +335,20 @@ private String escapeForTableCell(LastTwoLinesBufferingWriter writer, String tex
// Public protected methods
// ----------------------------------------------------------------------
+ protected static MarkdownSink newInstance(Writer writer) {
+ LastTwoLinesBufferingWriter bufferingWriter = new LastTwoLinesBufferingWriter(writer);
+ return new MarkdownSink(bufferingWriter, new PrintWriter(bufferingWriter));
+ }
+
/**
* Constructor, initialize the Writer and the variables.
*
* @param writer not null writer to write the result. Should be an UTF-8 Writer.
*/
- protected MarkdownSink(Writer writer) {
- this.bufferingWriter = new LastTwoLinesBufferingWriter(writer);
- this.writer = new PrintWriter(bufferingWriter);
+ private MarkdownSink(LastTwoLinesBufferingWriter bufferingWriter, PrintWriter writer) {
+ super(writer);
+ this.bufferingWriter = bufferingWriter;
+ this.writer = writer;
init();
}
@@ -467,8 +476,8 @@ protected void init() {
this.tableHeaderCellFlag = false;
this.cellCount = 0;
this.cellJustif = null;
- this.elementContextStack.clear();
- this.inlineStack.clear();
+ this.elementContextStack = Collections.asLifoQueue(new LinkedList<>());
+ this.inlineStack = Collections.asLifoQueue(new LinkedList<>());
// always set a default context (at least for tests not emitting a body)
elementContextStack.add(ElementContext.BODY);
}
@@ -539,6 +548,26 @@ public void date_() {
}
}
+ @Override
+ public void section(int level, SinkEventAttributes attributes) {
+ // not supported as often used around sectionTitles which would otherwise no longer be emitted as markdown
+ }
+
+ @Override
+ public void section_(int level) {
+ // not supported as often used around sectionTitles which would otherwise no longer be emitted as markdown
+ }
+
+ @Override
+ public void header(SinkEventAttributes attributes) {
+ // not supported as often used around sectionTitles which would otherwise no longer be emitted as markdown
+ }
+
+ @Override
+ public void header_() {
+ // not supported as often used around sectionTitles which would otherwise no longer be emitted as markdown
+ }
+
@Override
public void sectionTitle(int level, SinkEventAttributes attributes) {
startContext(ElementContext.HEADING);
@@ -556,6 +585,13 @@ public void sectionTitle_(int level) {
}
}
+ @Override
+ public void list(SinkEventAttributes attributes) {
+ if (elementContextStack.element().isHtml()) {
+ super.list(attributes);
+ }
+ }
+
@Override
public void list_() {
ensureBeginningOfLine();
@@ -641,9 +677,9 @@ public void pageBreak() {
@Override
public void paragraph(SinkEventAttributes attributes) {
+ ensureBlankLine();
// ignore paragraphs outside container contexts
if (elementContextStack.element().isContainer()) {
- ensureBlankLine();
writeUnescaped(getLinePrefix());
}
}
@@ -658,33 +694,49 @@ public void paragraph_() {
@Override
public void verbatim(SinkEventAttributes attributes) {
- // if no source attribute, then don't emit an info string
- startContext(ElementContext.CODE_BLOCK);
- writeUnescaped(VERBATIM_START_MARKUP);
- if (attributes != null && attributes.containsAttributes(SinkEventAttributeSet.SOURCE)) {
- writeUnescaped("unknown"); // unknown language
+ if (elementContextStack.element().isHtml()) {
+ super.verbatim(attributes);
+ } else {
+ // if no source attribute, then don't emit an info string
+ startContext(ElementContext.CODE_BLOCK);
+ writeUnescaped(VERBATIM_START_MARKUP);
+ if (attributes != null && attributes.containsAttributes(SinkEventAttributeSet.SOURCE)) {
+ writeUnescaped("unknown"); // unknown language
+ }
+ writeUnescaped(EOL);
+ writeUnescaped(getLinePrefix());
}
- writeUnescaped(EOL);
- writeUnescaped(getLinePrefix());
}
@Override
public void verbatim_() {
- ensureBeginningOfLine();
- writeUnescaped(getLinePrefix());
- writeUnescaped(VERBATIM_END_MARKUP + BLANK_LINE);
- endContext(ElementContext.CODE_BLOCK);
+ if (elementContextStack.element().isHtml()) {
+ super.verbatim_();
+ } else {
+ ensureBeginningOfLine();
+ writeUnescaped(getLinePrefix());
+ writeUnescaped(VERBATIM_END_MARKUP + BLANK_LINE);
+ endContext(ElementContext.CODE_BLOCK);
+ }
}
@Override
public void blockquote(SinkEventAttributes attributes) {
- startContext(ElementContext.BLOCKQUOTE);
- writeUnescaped(BLOCKQUOTE_START_MARKUP);
+ if (elementContextStack.element().isHtml()) {
+ super.blockquote(attributes);
+ } else {
+ startContext(ElementContext.BLOCKQUOTE);
+ writeUnescaped(BLOCKQUOTE_START_MARKUP);
+ }
}
@Override
public void blockquote_() {
- endContext(ElementContext.BLOCKQUOTE);
+ if (elementContextStack.element().isHtml()) {
+ super.blockquote_();
+ } else {
+ endContext(ElementContext.BLOCKQUOTE);
+ }
}
@Override
@@ -696,58 +748,82 @@ public void horizontalRule(SinkEventAttributes attributes) {
@Override
public void table(SinkEventAttributes attributes) {
- ensureBlankLine();
- writeUnescaped(getLinePrefix());
+ if (elementContextStack.element().isHtml()) {
+ super.table(attributes);
+ } else {
+ ensureBlankLine();
+ writeUnescaped(getLinePrefix());
+ }
+ }
+
+ @Override
+ public void table_() {
+ if (elementContextStack.element().isHtml()) {
+ super.table_();
+ }
}
@Override
public void tableRows(int[] justification, boolean grid) {
- if (justification != null) {
- cellJustif = Arrays.stream(justification).boxed().collect(Collectors.toCollection(ArrayList::new));
+ if (elementContextStack.element().isHtml()) {
+ super.tableRows(justification, grid);
} else {
- cellJustif = new ArrayList<>();
+ if (justification != null) {
+ cellJustif = Arrays.stream(justification).boxed().collect(Collectors.toCollection(ArrayList::new));
+ } else {
+ cellJustif = new ArrayList<>();
+ }
+ // grid flag is not supported
+ isFirstTableRow = true;
}
- // grid flag is not supported
- isFirstTableRow = true;
}
@Override
public void tableRows_() {
- cellJustif = null;
+ if (elementContextStack.element().isHtml()) {
+ super.tableRows_();
+ } else {
+ cellJustif = null;
+ }
}
@Override
public void tableRow(SinkEventAttributes attributes) {
- startContext(ElementContext.TABLE_ROW);
- cellCount = 0;
+ if (elementContextStack.element().isHtml()) {
+ super.tableRow(attributes);
+ } else {
+ startContext(ElementContext.TABLE_ROW);
+ cellCount = 0;
+ }
}
@Override
public void tableRow_() {
- String buffer = consumeBuffer();
- endContext(ElementContext.TABLE_ROW);
- if (isFirstTableRow && !tableHeaderCellFlag) {
- // emit empty table header as this is mandatory for GFM table extension
- // (https://stackoverflow.com/a/17543474/5155923)
- writeEmptyTableHeader();
- writeTableDelimiterRow();
- tableHeaderCellFlag = false;
- isFirstTableRow = false;
- // afterwards emit the first row
- }
-
- writeUnescaped(TABLE_ROW_PREFIX);
- writeUnescaped(buffer);
- writeUnescaped(EOL);
-
- if (isFirstTableRow) {
- // emit delimiter row
- writeTableDelimiterRow();
- isFirstTableRow = false;
+ if (elementContextStack.element().isHtml()) {
+ super.tableRow_();
+ } else {
+ String buffer = consumeBuffer();
+ endContext(ElementContext.TABLE_ROW);
+ if (isFirstTableRow && !tableHeaderCellFlag) {
+ // emit empty table header as this is mandatory for GFM table extension
+ // (https://stackoverflow.com/a/17543474/5155923)
+ writeEmptyTableHeader();
+ writeTableDelimiterRow();
+ tableHeaderCellFlag = false;
+ isFirstTableRow = false;
+ // afterwards emit the first row
+ }
+ writeUnescaped(TABLE_ROW_PREFIX);
+ writeUnescaped(buffer);
+ writeUnescaped(EOL);
+ if (isFirstTableRow) {
+ // emit delimiter row
+ writeTableDelimiterRow();
+ isFirstTableRow = false;
+ }
+ // only reset cell count if this is the last row
+ cellCount = 0;
}
-
- // only reset cell count if this is the last row
- cellCount = 0;
}
private void writeEmptyTableHeader() {
@@ -789,30 +865,34 @@ private void writeTableDelimiterRow() {
@Override
public void tableCell(SinkEventAttributes attributes) {
- startContext(ElementContext.TABLE_CELL);
- if (attributes != null) {
- // evaluate alignment attributes
- final int cellJustification;
- if (attributes.containsAttributes(SinkEventAttributeSet.LEFT)) {
- cellJustification = Sink.JUSTIFY_LEFT;
- } else if (attributes.containsAttributes(SinkEventAttributeSet.RIGHT)) {
- cellJustification = Sink.JUSTIFY_RIGHT;
- } else if (attributes.containsAttributes(SinkEventAttributeSet.CENTER)) {
- cellJustification = Sink.JUSTIFY_CENTER;
- } else {
- cellJustification = -1;
- }
- if (cellJustification > -1) {
- if (cellJustif.size() > cellCount) {
- cellJustif.set(cellCount, cellJustification);
- } else if (cellJustif.size() == cellCount) {
- cellJustif.add(cellJustification);
+ if (elementContextStack.element().isHtml()) {
+ super.tableCell(attributes);
+ } else {
+ startContext(ElementContext.TABLE_CELL);
+ if (attributes != null) {
+ // evaluate alignment attributes
+ final int cellJustification;
+ if (attributes.containsAttributes(SinkEventAttributeSet.LEFT)) {
+ cellJustification = Sink.JUSTIFY_LEFT;
+ } else if (attributes.containsAttributes(SinkEventAttributeSet.RIGHT)) {
+ cellJustification = Sink.JUSTIFY_RIGHT;
+ } else if (attributes.containsAttributes(SinkEventAttributeSet.CENTER)) {
+ cellJustification = Sink.JUSTIFY_CENTER;
} else {
- // create non-existing justifications for preceding columns
- for (int precedingCol = cellJustif.size(); precedingCol < cellCount; precedingCol++) {
- cellJustif.add(Sink.JUSTIFY_DEFAULT);
+ cellJustification = -1;
+ }
+ if (cellJustification > -1) {
+ if (cellJustif.size() > cellCount) {
+ cellJustif.set(cellCount, cellJustification);
+ } else if (cellJustif.size() == cellCount) {
+ cellJustif.add(cellJustification);
+ } else {
+ // create non-existing justifications for preceding columns
+ for (int precedingCol = cellJustif.size(); precedingCol < cellCount; precedingCol++) {
+ cellJustif.add(Sink.JUSTIFY_DEFAULT);
+ }
+ cellJustif.add(cellJustification);
}
- cellJustif.add(cellJustification);
}
}
}
@@ -820,18 +900,30 @@ public void tableCell(SinkEventAttributes attributes) {
@Override
public void tableHeaderCell(SinkEventAttributes attributes) {
- tableCell(attributes);
- tableHeaderCellFlag = true;
+ if (elementContextStack.element().isHtml()) {
+ super.tableHeaderCell(attributes);
+ } else {
+ tableCell(attributes);
+ tableHeaderCellFlag = true;
+ }
}
@Override
public void tableCell_() {
- endTableCell();
+ if (elementContextStack.element().isHtml()) {
+ super.tableCell_();
+ } else {
+ endTableCell();
+ }
}
@Override
public void tableHeaderCell_() {
- endTableCell();
+ if (elementContextStack.element().isHtml()) {
+ super.tableHeaderCell_();
+ } else {
+ endTableCell();
+ }
}
/**
@@ -845,42 +937,76 @@ private void endTableCell() {
@Override
public void tableCaption(SinkEventAttributes attributes) {
- elementContextStack.add(ElementContext.TABLE_CAPTION);
+ if (elementContextStack.element().isHtml()) {
+ super.tableCaption(attributes);
+ } else {
+ elementContextStack.add(ElementContext.TABLE_CAPTION);
+ }
}
@Override
public void tableCaption_() {
- endContext(ElementContext.TABLE_CAPTION);
+ if (elementContextStack.element().isHtml()) {
+ super.tableCaption_();
+ } else {
+ endContext(ElementContext.TABLE_CAPTION);
+ }
}
@Override
public void figure(SinkEventAttributes attributes) {
- figureSrc = null;
- startContext(ElementContext.FIGURE);
+ if (elementContextStack.element().isHtml()) {
+ super.figure(attributes);
+ } else {
+ figureSrc = null;
+ startContext(ElementContext.FIGURE);
+ }
+ }
+
+ @Override
+ public void figureCaption(SinkEventAttributes attributes) {
+ if (elementContextStack.element().isHtml()) {
+ super.figureCaption(attributes);
+ }
+ }
+
+ @Override
+ public void figureCaption_() {
+ if (elementContextStack.element().isHtml()) {
+ super.figureCaption_();
+ }
}
@Override
public void figureGraphics(String name, SinkEventAttributes attributes) {
- figureSrc = name;
- // is it a standalone image (outside a figure)?
- if (elementContextStack.peek() != ElementContext.FIGURE) {
- Object alt = attributes.getAttribute(SinkEventAttributes.ALT);
- if (alt == null) {
- alt = "";
+ if (elementContextStack.element().isHtml()) {
+ super.figureGraphics(name, attributes);
+ } else {
+ figureSrc = name;
+ // is it a standalone image (outside a figure)?
+ if (elementContextStack.peek() != ElementContext.FIGURE) {
+ Object alt = attributes.getAttribute(SinkEventAttributes.ALT);
+ if (alt == null) {
+ alt = "";
+ }
+ writeImage(elementContextStack.element().escape(bufferingWriter, alt.toString()), name);
}
- writeImage(elementContextStack.element().escape(bufferingWriter, alt.toString()), name);
}
}
@Override
public void figure_() {
- StringBuilder buffer = getCurrentBuffer();
- String label = "";
- if (buffer != null) {
- label = buffer.toString();
+ if (elementContextStack.element().isHtml()) {
+ super.figure_();
+ } else {
+ StringBuilder buffer = getCurrentBuffer();
+ String label = "";
+ if (buffer != null) {
+ label = buffer.toString();
+ }
+ endContext(ElementContext.FIGURE);
+ writeImage(label, figureSrc);
}
- endContext(ElementContext.FIGURE);
- writeImage(label, figureSrc);
}
private void writeImage(String alt, String src) {
@@ -890,123 +1016,129 @@ private void writeImage(String alt, String src) {
}
public void anchor(String name, SinkEventAttributes attributes) {
- // emit html anchor as markdown does not support anchors
- MutableAttributeSet atts = SinkUtils.filterAttributes(attributes, SinkUtils.SINK_BASE_ATTRIBUTES);
-
- String id = name;
-
- if (!DoxiaUtils.isValidId(id)) {
- id = DoxiaUtils.encodeId(name);
-
- LOGGER.debug("{}Modified invalid anchor name '{}' to '{}'", getLocationLogPrefix(), name, id);
+ super.anchor(name, attributes);
+ if (!elementContextStack.element().isHtml()) {
+ // close anchor tag immediately otherwise markdown would not be allowed afterwards
+ writeUnescaped("");
}
-
- MutableAttributeSet att = new SinkEventAttributeSet();
- att.addAttribute(SinkEventAttributes.ID, id);
- att.addAttributes(atts);
- StringBuilder htmlAnchor = new StringBuilder("");
- htmlAnchor.append(""); // close anchor tag immediately otherwise markdown would not be allowed afterwards
- writeUnescaped(htmlAnchor.toString());
}
@Override
public void anchor_() {
- // anchor is always empty html element, i.e. already closed with anchor()
+ if (elementContextStack.element().isHtml()) {
+ super.anchor_();
+ } else {
+ // anchor is always empty html element, i.e. already closed with anchor()
+ }
}
public void link(String name, SinkEventAttributes attributes) {
- if (elementContextStack.element() == ElementContext.CODE_BLOCK) {
- LOGGER.warn("{}Ignoring unsupported link inside code block", getLocationLogPrefix());
- } else if (elementContextStack.element() == ElementContext.CODE_SPAN) {
- // emit link outside the code span, i.e. insert at the beginning of the buffer
- getCurrentBuffer().insert(0, LINK_START_1_MARKUP);
- linkName = name;
+ if (elementContextStack.element().isHtml()) {
+ super.link(name, attributes);
} else {
- writeUnescaped(LINK_START_1_MARKUP);
- linkName = name;
+ if (elementContextStack.element() == ElementContext.CODE_BLOCK) {
+ LOGGER.warn("{}Ignoring unsupported link inside code block", getLocationLogPrefix());
+ } else if (elementContextStack.element() == ElementContext.CODE_SPAN) {
+ // emit link outside the code span, i.e. insert at the beginning of the buffer
+ getCurrentBuffer().insert(0, LINK_START_1_MARKUP);
+ linkName = name;
+ } else {
+ writeUnescaped(LINK_START_1_MARKUP);
+ linkName = name;
+ }
}
}
@Override
public void link_() {
- if (elementContextStack.element() == ElementContext.CODE_BLOCK) {
- return;
- } else if (elementContextStack.element() == ElementContext.CODE_SPAN) {
- // defer emitting link end markup until inline_() is called
- StringBuilder linkEndMarkup = new StringBuilder();
- linkEndMarkup.append(LINK_START_2_MARKUP);
- linkEndMarkup.append(linkName);
- linkEndMarkup.append(LINK_END_MARKUP);
- Queue endMarkups = new LinkedList<>(inlineStack.poll());
- endMarkups.add(linkEndMarkup.toString());
- inlineStack.add(endMarkups);
+ if (elementContextStack.element().isHtml()) {
+ super.link_();
} else {
- writeUnescaped(LINK_START_2_MARKUP + linkName + LINK_END_MARKUP);
+ if (elementContextStack.element() == ElementContext.CODE_BLOCK) {
+ return;
+ } else if (elementContextStack.element() == ElementContext.CODE_SPAN) {
+ // defer emitting link end markup until inline_() is called
+ StringBuilder linkEndMarkup = new StringBuilder();
+ linkEndMarkup.append(LINK_START_2_MARKUP);
+ linkEndMarkup.append(linkName);
+ linkEndMarkup.append(LINK_END_MARKUP);
+ Queue endMarkups = new LinkedList<>(inlineStack.poll());
+ endMarkups.add(linkEndMarkup.toString());
+ inlineStack.add(endMarkups);
+ } else {
+ writeUnescaped(LINK_START_2_MARKUP + linkName + LINK_END_MARKUP);
+ }
+ linkName = null;
}
- linkName = null;
}
@Override
public void inline(SinkEventAttributes attributes) {
- Queue endMarkups = Collections.asLifoQueue(new LinkedList<>());
-
- boolean requiresHtml = elementContextStack.element() == ElementContext.HTML_BLOCK;
- if (attributes != null
- && elementContextStack.element() != ElementContext.CODE_BLOCK
- && elementContextStack.element() != ElementContext.CODE_SPAN) {
- // code excludes other styles in markdown
- if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "code")
- || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "monospaced")
- || attributes.containsAttribute(SinkEventAttributes.STYLE, "monospaced")) {
- if (requiresHtml) {
- writeUnescaped("");
- endMarkups.add("");
- } else {
- startContext(ElementContext.CODE_SPAN);
- writeUnescaped(MONOSPACED_START_MARKUP);
- endMarkups.add(MONOSPACED_END_MARKUP);
- }
- } else {
- // in XHTML "" is used, but some tests still rely on the outdated ""
- if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "emphasis")
- || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "italic")
- || attributes.containsAttribute(SinkEventAttributes.STYLE, "italic")) {
+ if (elementContextStack.element().isHtml()) {
+ super.inline(attributes);
+ } else {
+ Queue endMarkups = Collections.asLifoQueue(new LinkedList<>());
+
+ boolean requiresHtml = elementContextStack.element() == ElementContext.HTML_BLOCK;
+ if (attributes != null
+ && elementContextStack.element() != ElementContext.CODE_BLOCK
+ && elementContextStack.element() != ElementContext.CODE_SPAN) {
+ // code excludes other styles in markdown
+ if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "code")
+ || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "monospaced")
+ || attributes.containsAttribute(SinkEventAttributes.STYLE, "monospaced")) {
if (requiresHtml) {
- writeUnescaped("");
- endMarkups.add("");
+ writeUnescaped("");
+ endMarkups.add("");
} else {
- writeUnescaped(ITALIC_START_MARKUP);
- endMarkups.add(ITALIC_END_MARKUP);
+ startContext(ElementContext.CODE_SPAN);
+ writeUnescaped(MONOSPACED_START_MARKUP);
+ endMarkups.add(MONOSPACED_END_MARKUP);
}
- }
- // in XHTML "" is used, but some tests still rely on the outdated ""
- if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "strong")
- || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "bold")
- || attributes.containsAttribute(SinkEventAttributes.STYLE, "bold")) {
- if (requiresHtml) {
- writeUnescaped("");
- endMarkups.add("");
- } else {
- writeUnescaped(BOLD_START_MARKUP);
- endMarkups.add(BOLD_END_MARKUP);
+ } else {
+ // in XHTML "" is used, but some tests still rely on the outdated ""
+ if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "emphasis")
+ || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "italic")
+ || attributes.containsAttribute(SinkEventAttributes.STYLE, "italic")) {
+ if (requiresHtml) {
+ writeUnescaped("");
+ endMarkups.add("");
+ } else {
+ writeUnescaped(ITALIC_START_MARKUP);
+ endMarkups.add(ITALIC_END_MARKUP);
+ }
+ }
+ // in XHTML "" is used, but some tests still rely on the outdated ""
+ if (attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "strong")
+ || attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "bold")
+ || attributes.containsAttribute(SinkEventAttributes.STYLE, "bold")) {
+ if (requiresHtml) {
+ writeUnescaped("");
+ endMarkups.add("");
+ } else {
+ writeUnescaped(BOLD_START_MARKUP);
+ endMarkups.add(BOLD_END_MARKUP);
+ }
}
}
}
+ inlineStack.add(endMarkups);
}
- inlineStack.add(endMarkups);
}
@Override
public void inline_() {
- for (String endMarkup : inlineStack.remove()) {
- if (endMarkup.equals(MONOSPACED_END_MARKUP)) {
- String buffer = getCurrentBuffer().toString();
- endContext(ElementContext.CODE_SPAN);
- writeUnescaped(buffer);
+ if (elementContextStack.element().isHtml()) {
+ super.inline_();
+ } else {
+ for (String endMarkup : inlineStack.remove()) {
+ if (endMarkup.equals(MONOSPACED_END_MARKUP)) {
+ String buffer = getCurrentBuffer().toString();
+ endContext(ElementContext.CODE_SPAN);
+ writeUnescaped(buffer);
+ }
+ writeUnescaped(endMarkup);
}
- writeUnescaped(endMarkup);
}
}
@@ -1057,27 +1189,32 @@ public void nonBreakingSpace() {
@Override
public void text(String text, SinkEventAttributes attributes) {
- if (attributes != null) {
- inline(attributes);
- }
- ElementContext currentContext = elementContextStack.element();
- if (currentContext == ElementContext.TABLE_CAPTION) {
- // table caption cannot even be emitted via XHTML in markdown as there is no suitable location
- LOGGER.warn("{}Ignoring unsupported table caption in Markdown", getLocationLogPrefix());
+ if (elementContextStack.element().isHtml()) {
+ super.text(text, attributes);
} else {
- String unifiedText = currentContext.escape(bufferingWriter, unifyEOLs(text));
- // ignore newlines only, because those are emitted often coming from linebreaks in HTML with no semantical
- // meaning
- if (!unifiedText.equals(EOL)) {
- String prefix = getLinePrefix();
- if (prefix.length() > 0) {
- unifiedText = unifiedText.replaceAll(EOL, EOL + prefix);
+ if (attributes != null) {
+ inline(attributes);
+ }
+ ElementContext currentContext = elementContextStack.element();
+ if (currentContext == ElementContext.TABLE_CAPTION) {
+ // table caption cannot even be emitted via XHTML in markdown as there is no suitable location
+ LOGGER.warn("{}Ignoring unsupported table caption in Markdown", getLocationLogPrefix());
+ } else {
+ String unifiedText = currentContext.escape(bufferingWriter, unifyEOLs(text));
+ // ignore newlines only, because those are emitted often coming from linebreaks in HTML with no
+ // semantical
+ // meaning
+ if (!unifiedText.equals(EOL)) {
+ String prefix = getLinePrefix();
+ if (prefix.length() > 0) {
+ unifiedText = unifiedText.replaceAll(EOL, EOL + prefix);
+ }
}
+ writeUnescaped(unifiedText);
+ }
+ if (attributes != null) {
+ inline_();
}
- writeUnescaped(unifiedText);
- }
- if (attributes != null) {
- inline_();
}
}
@@ -1086,16 +1223,6 @@ public void rawText(String text) {
writeUnescaped(text);
}
- @Override
- public void comment(String comment) {
- comment(comment, false);
- }
-
- @Override
- public void comment(String comment, boolean endsWithLineBreak) {
- rawText(Xhtml5BaseSink.encodeAsHtmlComment(comment, endsWithLineBreak, getLocationLogPrefix()));
- }
-
/**
* {@inheritDoc}
*
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSinkFactory.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSinkFactory.java
index 6c0b84216..4703a5742 100644
--- a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSinkFactory.java
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSinkFactory.java
@@ -35,6 +35,6 @@ public class MarkdownSinkFactory extends AbstractTextSinkFactory {
protected Sink createSink(Writer writer, String encoding) {
// encoding can safely be ignored since it isn't written into the generated Markdown source
- return new MarkdownSink(writer);
+ return MarkdownSink.newInstance(writer);
}
}
diff --git a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
index f8b847c3c..f2f785048 100644
--- a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
+++ b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
@@ -51,7 +51,7 @@ protected String outputExtension() {
}
protected Sink createSink(Writer writer) {
- return new MarkdownSink(writer);
+ return MarkdownSink.newInstance(writer);
}
protected boolean isXmlSink() {
@@ -79,15 +79,15 @@ protected String getBodyBlock() {
}
protected String getArticleBlock() {
- return "";
+ return "";
}
protected String getNavigationBlock() {
- return "";
+ return "";
}
protected String getSidebarBlock() {
- return "";
+ return "";
}
protected String getSectionBlock(String title, int level) {
@@ -119,15 +119,16 @@ protected String getSection6Block(String title) {
}
protected String getHeaderBlock() {
+ // never emitted by Markdown sink as otherwise too often markdown could not be used
return "";
}
protected String getContentBlock() {
- return "";
+ return "" + EOL + "";
}
protected String getFooterBlock() {
- return "";
+ return "";
}
protected String getListBlock(String item) {
@@ -194,15 +195,15 @@ protected String getParagraphBlock(String text) {
}
protected String getDataBlock(String value, String text) {
- return text;
+ return "" + text + "";
}
protected String getTimeBlock(String datetime, String text) {
- return text;
+ return "";
}
protected String getAddressBlock(String text) {
- return text;
+ return "" + text + "";
}
protected String getBlockquoteBlock(String text) {
@@ -210,7 +211,7 @@ protected String getBlockquoteBlock(String text) {
}
protected String getDivisionBlock(String text) {
- return text;
+ return "" + text + "
";
}
protected String getVerbatimBlock(String text) {
@@ -275,7 +276,7 @@ protected String getLineBreakBlock() {
}
protected String getLineBreakOpportunityBlock() {
- return "";
+ return "";
}
protected String getNonBreakingSpaceBlock() {
@@ -576,4 +577,26 @@ void nestedListBeingTight() {
+ "- item 3" + EOL;
assertEquals(expected, getSinkContent());
}
+
+ @Test
+ public void testLinkInsideHtmlSection() {
+ try (Sink sink = getSink()) {
+ sink.definitionList();
+ sink.definedTerm();
+ sink.text("question1");
+ sink.definedTerm_();
+ sink.definition();
+ sink.link("#top");
+ sink.text("[top]");
+ sink.link_();
+ sink.definition_();
+ sink.definitionList_();
+ }
+ String expected = "" + EOL
+ + "- question1
" + EOL
+ + "- [top]
" + EOL
+ + "
" + EOL
+ + EOL;
+ assertEquals(expected, getSinkContent());
+ }
}