Skip to content

Commit 2821df1

Browse files
(v2.2.x) #763 missing breadcrumb in maven site module (#769)
* Set document title, author(s) and date for Maven site integration fixes #763 --------- Co-authored-by: Alexander Kriegisch <[email protected]>
1 parent 8aae0db commit 2821df1

File tree

12 files changed

+495
-121
lines changed

12 files changed

+495
-121
lines changed

CHANGELOG.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/main[co
1313

1414
== Unreleased
1515

16+
Improvements::
17+
18+
* Push Asiidoctor header metadata (author(s), conversion time and title) to maven-site pages (#769)
19+
20+
Bug Fixes::
21+
22+
* Fix breadcrumbs not showing the document title in maven-site pages (#763)
23+
1624
== v2.2.5 (2024-01-11)
1725

1826
Bug Fixes::
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
* Maven Site Integration
22
** xref:introduction.adoc[]
33
** xref:setup-and-configuration.adoc[]
4+
** xref:exposed-metadata.adoc[]
45
** xref:compatibility-matrix.adoc[]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
= Exposed metadata
2+
:asciidoctor-docs-url: https://docs.asciidoctor.org/asciidoc/latest
3+
:maven-site-plugin-docs-url: https://maven.apache.org/plugins/maven-site-plugin
4+
5+
The Asciidoctor Maven Site integration collaborates with Doxia to expose some of its information.
6+
7+
== Document Header metadata
8+
9+
The following elements from the {asciidoctor-docs-url}/document/header/[header] are integrated:
10+
11+
document title:: used to inform the {maven-site-plugin-docs-url}/examples/sitedescriptor.html#Breadcrumbs[breadcrumb] line when these are enabled.
12+
13+
author(s):: full representation (full name and email) will be present as HTML `<meta name="author" ... >` tags inside the HTML `<head>`.
14+
In case of multiple authors, each one will appear in a distinct `meta` element.
15+
16+
revision date:: the header revision date value will be presented as-is in a `<meta name="date" ... >` element.
17+
Alternatively, if not set, the generated value of `docdatetime` will be used.

src/it/maven-site-plugin/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<plugin>
2323
<groupId>org.apache.maven.plugins</groupId>
2424
<artifactId>maven-project-info-reports-plugin</artifactId>
25-
<version>3.1.2</version>
25+
<version>3.4.5</version>
2626
</plugin>
2727
<!-- tag::plugin-decl[] -->
2828
<plugin>

src/it/maven-site-plugin/src/site/asciidoc/file-with-toc.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
= File with TOC
2+
The Author
3+
:docdatetime: 2024-02-07 23:36:29
24
:toc:
35

46
[.lead]

src/it/maven-site-plugin/src/site/site.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<project name="Maven Site Plugin IT">
22
<body>
3+
<breadcrumbs>
4+
<item name="Doxia" href="https://maven.apache.org/doxia/index.html"/>
5+
<item name="Trunk" href="https://maven.apache.org/doxia/doxia/index.html"/>
6+
</breadcrumbs>
37
<menu name="AsciiDoc Pages">
48
<item name="File with TOC" href="/file-with-toc.html"/>
59
</menu>

src/it/maven-site-plugin/validate.bsh

Lines changed: 0 additions & 111 deletions
This file was deleted.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import java.nio.charset.StandardCharsets
2+
import java.nio.file.Files
3+
import java.util.regex.Pattern
4+
5+
File outputDir = new File(basedir, "target/site")
6+
7+
String[] expectedFiles = [
8+
"file-with-toc.html"
9+
]
10+
11+
String[] unexpectedFiles = [
12+
"_include.html"
13+
]
14+
15+
class PatternCapturer {
16+
17+
private final Pattern pattern
18+
private final List<String> hits
19+
20+
PatternCapturer(String pattern) {
21+
this.pattern = Pattern.compile(pattern)
22+
this.hits = new ArrayList()
23+
}
24+
25+
26+
String tryMatches(String text) {
27+
def matcher = pattern.matcher(text)
28+
if (matcher.matches()) {
29+
def group = matcher.group(1)
30+
hits.add(group)
31+
return group
32+
}
33+
return null
34+
}
35+
36+
void remove(String text) {
37+
hits.remove(text)
38+
}
39+
40+
int size() {
41+
return hits.size()
42+
}
43+
44+
List<String> getHits() {
45+
return hits
46+
}
47+
}
48+
49+
for (String expectedFile : expectedFiles) {
50+
File file = new File(outputDir, expectedFile)
51+
System.out.println("Checking for presence of $file")
52+
if (!file.exists() || !file.isFile()) {
53+
throw new Exception("Missing file $file")
54+
}
55+
56+
def lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8)
57+
System.out.println("Ensuring IDs match TOC links")
58+
59+
// == Assert TOC ==
60+
def tocEntryCapturer = new PatternCapturer("<li><a href=\"#(.*?)\">.*")
61+
def elementIdCapturer = new PatternCapturer(".* id=\"(.*?)\".*")
62+
63+
for (String line : lines) {
64+
tocEntryCapturer.tryMatches(line)
65+
66+
String match = elementIdCapturer.tryMatches(line)
67+
if (match != null) {
68+
tocEntryCapturer.remove(match)
69+
}
70+
}
71+
if (tocEntryCapturer.size() != 0) {
72+
throw new Exception("Couldn't find matching IDs for the following TOC entries: ${tocEntryCapturer.getHits()}")
73+
}
74+
75+
// == Assert includes ==
76+
boolean includeResolved = false
77+
boolean sourceHighlighted = false
78+
79+
for (String line : lines) {
80+
if (!includeResolved && line.contains("Content included from the file ")) {
81+
includeResolved = true
82+
} else if (!sourceHighlighted && line.contains("<span style=\"color:#070;font-weight:bold\">&lt;plugin&gt;</span>")) {
83+
sourceHighlighted = true;
84+
}
85+
}
86+
if (!includeResolved) {
87+
throw new Exception("Include file was not resolved")
88+
}
89+
if (!sourceHighlighted) {
90+
throw new Exception("Source code was not highlighted")
91+
}
92+
93+
// validate that maven properties are replaced same as attributes
94+
boolean foundReplacement = false
95+
for (String line : lines) {
96+
if (line.contains("v1.2.3")) {
97+
foundReplacement = true
98+
break
99+
}
100+
}
101+
if (!foundReplacement) {
102+
throw new Exception("Maven properties not replaced")
103+
}
104+
105+
// == Assert header metadata ==
106+
def metaPattern = Pattern.compile( "<meta name=\"(author|date)\" content=\"(.*)\" />")
107+
boolean headFound = false
108+
Map<String,String> metaTags = new HashMap<>()
109+
110+
for (String line : lines) {
111+
if (!headFound) {
112+
headFound = line.endsWith("<head>")
113+
continue
114+
}
115+
if (line.endsWith("</head>")) break
116+
def matcher = metaPattern.matcher(line.trim())
117+
if (matcher.matches()) {
118+
metaTags.put(matcher.group(1), matcher.group(2))
119+
}
120+
}
121+
122+
if (metaTags['author'] != 'The Author')
123+
throw new RuntimeException("Author not found in $metaTags")
124+
if (metaTags['date'] != '2024-02-07 23:36:29')
125+
throw new RuntimeException("docdatetime not found in: $metaTags")
126+
127+
// assert breadcrumbs
128+
boolean breadcrumbTagFound = false
129+
boolean breadcrumbFound = false
130+
final String docTitle = "File with TOC"
131+
132+
for (String line : lines) {
133+
if (!breadcrumbTagFound) {
134+
breadcrumbTagFound = line.endsWith("<div id=\"breadcrumbs\">")
135+
continue
136+
}
137+
if (line.endsWith("</div>")) break
138+
breadcrumbFound = line.trim().equals(docTitle)
139+
}
140+
141+
if (!breadcrumbFound)
142+
throw new RuntimeException("No breadcrumb found: expected title: $docTitle")
143+
}
144+
145+
for (String unexpectedFile : unexpectedFiles) {
146+
File file = new File(outputDir, unexpectedFile)
147+
System.out.println("Checking for absence of $file")
148+
if (file.isFile()) {
149+
throw new Exception("Unexpected file $file")
150+
}
151+
}
152+
153+
return true

src/main/java/org/asciidoctor/maven/site/AsciidoctorDoxiaParser.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
import org.apache.maven.doxia.parser.Parser;
66
import org.apache.maven.doxia.sink.Sink;
77
import org.apache.maven.project.MavenProject;
8-
import org.asciidoctor.*;
8+
import org.asciidoctor.Asciidoctor;
9+
import org.asciidoctor.AttributesBuilder;
10+
import org.asciidoctor.OptionsBuilder;
11+
import org.asciidoctor.SafeMode;
912
import org.asciidoctor.maven.log.LogHandler;
1013
import org.asciidoctor.maven.log.LogRecordFormatter;
1114
import org.asciidoctor.maven.log.LogRecordsProcessors;
1215
import org.asciidoctor.maven.log.MemoryLogHandler;
16+
import org.asciidoctor.maven.site.SiteConverterDecorator.Result;
1317
import org.codehaus.plexus.component.annotations.Component;
1418
import org.codehaus.plexus.util.IOUtil;
1519
import org.codehaus.plexus.util.xml.Xpp3Dom;
@@ -75,8 +79,9 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
7579
final LogHandler logHandler = getLogHandlerConfig(siteConfig);
7680
final MemoryLogHandler memoryLogHandler = asciidoctorLoggingSetup(asciidoctor, logHandler, siteDirectory);
7781

78-
// QUESTION should we keep OptionsBuilder & AttributesBuilder separate for call to convertAsciiDoc?
79-
String asciidocHtml = convertAsciiDoc(asciidoctor, source, conversionConfig.getOptions());
82+
final SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
83+
final Result headerMetadata = siteConverter.process(source, conversionConfig.getOptions());
84+
8085
try {
8186
// process log messages according to mojo configuration
8287
new LogRecordsProcessors(logHandler, siteDirectory, errorMessage -> getLog().error(errorMessage))
@@ -85,9 +90,13 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
8590
throw new ParseException(exception.getMessage(), exception);
8691
}
8792

88-
sink.rawText(asciidocHtml);
93+
new HeadParser(sink)
94+
.parse(headerMetadata.getHeaderMetadata());
95+
96+
sink.rawText(headerMetadata.getHtml());
8997
}
9098

99+
91100
private MemoryLogHandler asciidoctorLoggingSetup(Asciidoctor asciidoctor, LogHandler logHandler, File siteDirectory) {
92101

93102
final MemoryLogHandler memoryLogHandler = new MemoryLogHandler(logHandler.getOutputToConsole(), siteDirectory,
@@ -140,9 +149,4 @@ private void requireLibrary(Asciidoctor asciidoctor, String require) {
140149
}
141150
}
142151
}
143-
144-
protected String convertAsciiDoc(Asciidoctor asciidoctor, String source, Options options) {
145-
return asciidoctor.convert(source, options);
146-
}
147-
148152
}

0 commit comments

Comments
 (0)