Skip to content

Commit c8b543a

Browse files
authored
Add support for description lists in parser-doxia-module (#772)
* Tested all examples from official docs * Update maven-plugin docs Closes #751
1 parent 19ddcdc commit c8b543a

File tree

8 files changed

+390
-27
lines changed

8 files changed

+390
-27
lines changed

asciidoctor-parser-doxia-module/src/it/maven-site-plugin/src/site/asciidoc/sample.adoc

+13
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,16 @@ public class HelloWorld {
7575
. Protons
7676
. Electrons
7777
. Neutrons
78+
79+
==== Description list
80+
81+
Operating Systems::
82+
Linux:::
83+
. Fedora
84+
* Desktop
85+
. Ubuntu
86+
* Desktop
87+
* Server
88+
BSD:::
89+
. FreeBSD
90+
. NetBSD

asciidoctor-parser-doxia-module/src/it/maven-site-plugin/validate.groovy

+19
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ new HtmlAsserter(htmlContent).with { asserter ->
4242
asserter.containsSectionTitle("Ordered list", 4)
4343
asserter.containsOrderedList("Protons", "Electrons", "Neutrons")
4444

45+
asserter.containsSectionTitle("Description list", 4)
46+
asserter.descriptionListTerm("Operating Systems")
47+
asserter.descriptionListTerm("Linux")
48+
asserter.contains("<li>Fedora")
49+
asserter.containsUnorderedList("Desktop")
50+
asserter.contains("<li>Ubuntu")
51+
asserter.containsUnorderedList("Desktop", "Server")
52+
asserter.descriptionListTerm("BSD")
53+
asserter.containsOrderedList("FreeBSD", "NetBSD")
4554
}
4655

4756
String strong(String text) {
@@ -111,6 +120,11 @@ class HtmlAsserter {
111120
return content.indexOf(value, lastAssertionCursor)
112121
}
113122

123+
void contains(String text) {
124+
def found = find(text)
125+
assertFound("HTML text", text, found)
126+
}
127+
114128
void containsDocumentTitle(String value) {
115129
def found = find("<h1>$value</h1>")
116130
assertFound("Document Title", value, found)
@@ -160,6 +174,11 @@ class HtmlAsserter {
160174
assertFound("Ordered list", values.join(','), found)
161175
}
162176

177+
void descriptionListTerm(String term) {
178+
def found = find("<dt>${term}</dt>")
179+
assertFound("Description list", term, found)
180+
}
181+
163182
void containsTable(int columns, int rows, List<String> headers, String caption) {
164183
def start = content.indexOf("<table", lastAssertionCursor)
165184
def end = content.indexOf("</table>", lastAssertionCursor) + "</table>".length()

asciidoctor-parser-doxia-module/src/main/java/org/asciidoctor/maven/site/ast/NodesSinker.java

+18-14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.apache.maven.doxia.sink.Sink;
88
import org.asciidoctor.ast.StructuralNode;
9+
import org.asciidoctor.maven.site.ast.processors.DescriptionListNodeProcessor;
910
import org.asciidoctor.maven.site.ast.processors.DocumentNodeProcessor;
1011
import org.asciidoctor.maven.site.ast.processors.ImageNodeProcessor;
1112
import org.asciidoctor.maven.site.ast.processors.ListItemNodeProcessor;
@@ -39,23 +40,26 @@ public NodesSinker(Sink sink) {
3940

4041
UnorderedListNodeProcessor unorderedListNodeProcessor = new UnorderedListNodeProcessor(sink);
4142
OrderedListNodeProcessor orderedListNodeProcessor = new OrderedListNodeProcessor(sink);
43+
DescriptionListNodeProcessor descriptionListNodeProcessor = new DescriptionListNodeProcessor(sink);
4244

4345
ListItemNodeProcessor listItemNodeProcessor = new ListItemNodeProcessor(sink);
44-
listItemNodeProcessor.setNodeProcessors(Arrays.asList(unorderedListNodeProcessor, orderedListNodeProcessor));
46+
listItemNodeProcessor.setNodeProcessors(Arrays.asList(unorderedListNodeProcessor, orderedListNodeProcessor, descriptionListNodeProcessor));
4547
unorderedListNodeProcessor.setItemNodeProcessor(listItemNodeProcessor);
4648
orderedListNodeProcessor.setItemNodeProcessor(listItemNodeProcessor);
49+
descriptionListNodeProcessor.setItemNodeProcessor(listItemNodeProcessor);
4750

4851
nodeProcessors = Arrays.asList(
49-
new DocumentNodeProcessor(sink),
50-
new ImageNodeProcessor(sink),
51-
new ListingNodeProcessor(sink),
52-
new LiteralNodeProcessor(sink),
53-
new ParagraphNodeProcessor(sink),
54-
new PreambleNodeProcessor(sink),
55-
new SectionNodeProcessor(sink),
56-
new TableNodeProcessor(sink),
57-
orderedListNodeProcessor,
58-
unorderedListNodeProcessor
52+
new DocumentNodeProcessor(sink),
53+
new ImageNodeProcessor(sink),
54+
new ListingNodeProcessor(sink),
55+
new LiteralNodeProcessor(sink),
56+
new ParagraphNodeProcessor(sink),
57+
new PreambleNodeProcessor(sink),
58+
new SectionNodeProcessor(sink),
59+
new TableNodeProcessor(sink),
60+
descriptionListNodeProcessor,
61+
orderedListNodeProcessor,
62+
unorderedListNodeProcessor
5963
);
6064
}
6165

@@ -72,8 +76,8 @@ private void processNode(StructuralNode node, int depth) {
7276
try {
7377
// Only one matches in current NodeProcessors implementation
7478
Optional<NodeProcessor> nodeProcessor = nodeProcessors.stream()
75-
.filter(np -> np.applies(node))
76-
.findFirst();
79+
.filter(np -> np.applies(node))
80+
.findFirst();
7781
if (nodeProcessor.isPresent()) {
7882
NodeProcessor processor = nodeProcessor.get();
7983
processor.process(node);
@@ -90,6 +94,6 @@ private void processNode(StructuralNode node, int depth) {
9094

9195
private void traverse(StructuralNode node, int depth) {
9296
node.getBlocks()
93-
.forEach(b -> processNode(b, depth + 1));
97+
.forEach(b -> processNode(b, depth + 1));
9498
}
9599
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.asciidoctor.maven.site.ast.processors;
2+
3+
import java.util.List;
4+
5+
import org.apache.maven.doxia.sink.Sink;
6+
import org.asciidoctor.ast.DescriptionList;
7+
import org.asciidoctor.ast.DescriptionListEntry;
8+
import org.asciidoctor.ast.ListItem;
9+
import org.asciidoctor.ast.StructuralNode;
10+
import org.asciidoctor.maven.site.ast.NodeProcessor;
11+
12+
/**
13+
* Description list processor.
14+
*
15+
* @author abelsromero
16+
* @since 3.0.0
17+
*/
18+
public class DescriptionListNodeProcessor extends AbstractSinkNodeProcessor implements NodeProcessor {
19+
20+
private ListItemNodeProcessor itemNodeProcessor;
21+
22+
/**
23+
* Constructor.
24+
*
25+
* @param sink Doxia {@link Sink}
26+
*/
27+
public DescriptionListNodeProcessor(Sink sink) {
28+
super(sink);
29+
}
30+
31+
/**
32+
* Inject a {@link ListItemNodeProcessor}.
33+
*
34+
* @param nodeProcessor {@link ListItemNodeProcessor}
35+
*/
36+
public void setItemNodeProcessor(ListItemNodeProcessor nodeProcessor) {
37+
this.itemNodeProcessor = nodeProcessor;
38+
}
39+
40+
@Override
41+
public boolean applies(StructuralNode node) {
42+
return "dlist".equals(node.getNodeName());
43+
}
44+
45+
@Override
46+
public boolean isTerminal(StructuralNode node) {
47+
return true;
48+
}
49+
50+
@Override
51+
public void process(StructuralNode node) {
52+
53+
final List<DescriptionListEntry> items = ((DescriptionList) node).getItems();
54+
final Sink sink = getSink();
55+
56+
if (!items.isEmpty()) {
57+
sink.definitionList();
58+
for (DescriptionListEntry item : items) {
59+
// About the model, see https://asciidoctor.zulipchat.com/#narrow/stream/279642-users/topic/.E2.9C.94.20Description.20List.20AST.20structure/near/419353063
60+
final ListItem term = item.getTerms().get(0);
61+
sink.definedTerm();
62+
sink.rawText(term.getText());
63+
sink.definedTerm_();
64+
65+
final ListItem description = item.getDescription();
66+
sink.definition();
67+
if (description.getBlocks().isEmpty()) {
68+
sink.rawText(description.getText());
69+
} else {
70+
itemNodeProcessor.process(description);
71+
}
72+
sink.definition_();
73+
}
74+
sink.definitionList_();
75+
}
76+
}
77+
}

asciidoctor-parser-doxia-module/src/main/java/org/asciidoctor/maven/site/ast/processors/ListItemNodeProcessor.java

+32-11
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,19 @@ public boolean applies(StructuralNode node) {
4545
public void process(StructuralNode node) {
4646
final ListItem item = (ListItem) node;
4747
final Sink sink = getSink();
48-
if (isUnorderedListItem(item))
49-
sink.listItem();
50-
else
51-
sink.numberedListItem();
48+
final ListType listType = getListType(item);
5249

53-
String text = item.getText();
50+
// description type does not require any action
51+
switch (listType) {
52+
case ordered:
53+
sink.numberedListItem();
54+
break;
55+
case unordered:
56+
sink.listItem();
57+
break;
58+
}
59+
60+
final String text = item.getText();
5461
sink.rawText(text == null ? "" : text);
5562

5663
for (StructuralNode subNode : node.getBlocks()) {
@@ -61,14 +68,28 @@ public void process(StructuralNode node) {
6168
}
6269
}
6370

64-
if (isUnorderedListItem(item))
65-
sink.listItem_();
66-
else
67-
sink.numberedListItem_();
71+
switch (listType) {
72+
case ordered:
73+
sink.numberedListItem_();
74+
break;
75+
case unordered:
76+
sink.listItem_();
77+
break;
78+
}
6879
}
6980

70-
private static boolean isUnorderedListItem(ListItem item) {
81+
private static ListType getListType(ListItem item) {
7182
final String marker = item.getMarker();
72-
return marker.startsWith("*") || marker.startsWith("-");
83+
if (marker == null) {
84+
return ListType.description;
85+
} else if (marker.startsWith("*") || marker.startsWith("-")) {
86+
return ListType.ordered;
87+
} else {
88+
return ListType.unordered;
89+
}
90+
}
91+
92+
enum ListType {
93+
ordered, unordered, description
7394
}
7495
}

0 commit comments

Comments
 (0)