Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(v2.2.x) #763 missing breadcrumb in maven site module #769

8 changes: 8 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/main[co

== Unreleased

Improvements::

* Push Asiidoctor header metadata (author(s), conversion time and title) to maven-site pages (#769)

Bug Fixes::

* Fix breadcrumbs not showing the document title in maven-site pages (#763)

== v2.2.5 (2024-01-11)

Bug Fixes::
Expand Down
1 change: 1 addition & 0 deletions docs/modules/site-integration/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
* Maven Site Integration
** xref:introduction.adoc[]
** xref:setup-and-configuration.adoc[]
** xref:exposed-metadata.adoc[]
** xref:compatibility-matrix.adoc[]
17 changes: 17 additions & 0 deletions docs/modules/site-integration/pages/exposed-metadata.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
= Exposed metadata
:asciidoctor-docs-url: https://docs.asciidoctor.org/asciidoc/latest
:maven-site-plugin-docs-url: https://maven.apache.org/plugins/maven-site-plugin

The Asciidoctor Maven Site integration collaborates with Doxia to expose some of its information.

== Document Header metadata

The following elements from the {asciidoctor-docs-url}/document/header/[header] are integrated:

document title:: used to inform the {maven-site-plugin-docs-url}/examples/sitedescriptor.html#Breadcrumbs[breadcrumb] line when these are enabled.

author(s):: full representation (full name and email) will be present as HTML `<meta name="author" ... >` tags inside the HTML `<head>`.
In case of multiple authors, each one will appear in a distinct `meta` element.

revision date:: the header revision date value will be presented as-is in a `<meta name="date" ... >` element.
Alternatively, if not set, the generated value of `docdatetime` will be used.
2 changes: 1 addition & 1 deletion src/it/maven-site-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.1.2</version>
<version>3.4.5</version>
</plugin>
<!-- tag::plugin-decl[] -->
<plugin>
Expand Down
2 changes: 2 additions & 0 deletions src/it/maven-site-plugin/src/site/asciidoc/file-with-toc.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
= File with TOC
The Author
:docdatetime: 2024-02-07 23:36:29
:toc:

[.lead]
Expand Down
4 changes: 4 additions & 0 deletions src/it/maven-site-plugin/src/site/site.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<project name="Maven Site Plugin IT">
<body>
<breadcrumbs>
<item name="Doxia" href="https://maven.apache.org/doxia/index.html"/>
<item name="Trunk" href="https://maven.apache.org/doxia/doxia/index.html"/>
</breadcrumbs>
<menu name="AsciiDoc Pages">
<item name="File with TOC" href="/file-with-toc.html"/>
</menu>
Expand Down
111 changes: 0 additions & 111 deletions src/it/maven-site-plugin/validate.bsh

This file was deleted.

153 changes: 153 additions & 0 deletions src/it/maven-site-plugin/validate.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.regex.Pattern

File outputDir = new File(basedir, "target/site")

String[] expectedFiles = [
"file-with-toc.html"
]

String[] unexpectedFiles = [
"_include.html"
]

class PatternCapturer {

private final Pattern pattern
private final List<String> hits

PatternCapturer(String pattern) {
this.pattern = Pattern.compile(pattern)
this.hits = new ArrayList()
}


String tryMatches(String text) {
def matcher = pattern.matcher(text)
if (matcher.matches()) {
def group = matcher.group(1)
hits.add(group)
return group
}
return null
}

void remove(String text) {
hits.remove(text)
}

int size() {
return hits.size()
}

List<String> getHits() {
return hits
}
}

for (String expectedFile : expectedFiles) {
File file = new File(outputDir, expectedFile)
System.out.println("Checking for presence of $file")
if (!file.exists() || !file.isFile()) {
throw new Exception("Missing file $file")
}

def lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8)
System.out.println("Ensuring IDs match TOC links")

// == Assert TOC ==
def tocEntryCapturer = new PatternCapturer("<li><a href=\"#(.*?)\">.*")
def elementIdCapturer = new PatternCapturer(".* id=\"(.*?)\".*")

for (String line : lines) {
tocEntryCapturer.tryMatches(line)

String match = elementIdCapturer.tryMatches(line)
if (match != null) {
tocEntryCapturer.remove(match)
}
}
if (tocEntryCapturer.size() != 0) {
throw new Exception("Couldn't find matching IDs for the following TOC entries: ${tocEntryCapturer.getHits()}")
}

// == Assert includes ==
boolean includeResolved = false
boolean sourceHighlighted = false

for (String line : lines) {
if (!includeResolved && line.contains("Content included from the file ")) {
includeResolved = true
} else if (!sourceHighlighted && line.contains("<span style=\"color:#070;font-weight:bold\">&lt;plugin&gt;</span>")) {
sourceHighlighted = true;
}
}
if (!includeResolved) {
throw new Exception("Include file was not resolved")
}
if (!sourceHighlighted) {
throw new Exception("Source code was not highlighted")
}

// validate that maven properties are replaced same as attributes
boolean foundReplacement = false
for (String line : lines) {
if (line.contains("v1.2.3")) {
foundReplacement = true
break
}
}
if (!foundReplacement) {
throw new Exception("Maven properties not replaced")
}

// == Assert header metadata ==
def metaPattern = Pattern.compile( "<meta name=\"(author|date)\" content=\"(.*)\" />")
boolean headFound = false
Map<String,String> metaTags = new HashMap<>()

for (String line : lines) {
if (!headFound) {
headFound = line.endsWith("<head>")
continue
}
if (line.endsWith("</head>")) break
def matcher = metaPattern.matcher(line.trim())
if (matcher.matches()) {
metaTags.put(matcher.group(1), matcher.group(2))
}
}

if (metaTags['author'] != 'The Author')
throw new RuntimeException("Author not found in $metaTags")
if (metaTags['date'] != '2024-02-07 23:36:29')
throw new RuntimeException("docdatetime not found in: $metaTags")

// assert breadcrumbs
boolean breadcrumbTagFound = false
boolean breadcrumbFound = false
final String docTitle = "File with TOC"

for (String line : lines) {
if (!breadcrumbTagFound) {
breadcrumbTagFound = line.endsWith("<div id=\"breadcrumbs\">")
continue
}
if (line.endsWith("</div>")) break
breadcrumbFound = line.trim().equals(docTitle)
}

if (!breadcrumbFound)
throw new RuntimeException("No breadcrumb found: expected title: $docTitle")
}

for (String unexpectedFile : unexpectedFiles) {
File file = new File(outputDir, unexpectedFile)
System.out.println("Checking for absence of $file")
if (file.isFile()) {
throw new Exception("Unexpected file $file")
}
}

return true
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.project.MavenProject;
import org.asciidoctor.*;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.AttributesBuilder;
import org.asciidoctor.OptionsBuilder;
import org.asciidoctor.SafeMode;
import org.asciidoctor.maven.log.LogHandler;
import org.asciidoctor.maven.log.LogRecordFormatter;
import org.asciidoctor.maven.log.LogRecordsProcessors;
import org.asciidoctor.maven.log.MemoryLogHandler;
import org.asciidoctor.maven.site.SiteConverterDecorator.Result;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
Expand Down Expand Up @@ -75,8 +79,9 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
final LogHandler logHandler = getLogHandlerConfig(siteConfig);
final MemoryLogHandler memoryLogHandler = asciidoctorLoggingSetup(asciidoctor, logHandler, siteDirectory);

// QUESTION should we keep OptionsBuilder & AttributesBuilder separate for call to convertAsciiDoc?
String asciidocHtml = convertAsciiDoc(asciidoctor, source, conversionConfig.getOptions());
final SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
final Result headerMetadata = siteConverter.process(source, conversionConfig.getOptions());

try {
// process log messages according to mojo configuration
new LogRecordsProcessors(logHandler, siteDirectory, errorMessage -> getLog().error(errorMessage))
Expand All @@ -85,9 +90,13 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
throw new ParseException(exception.getMessage(), exception);
}

sink.rawText(asciidocHtml);
new HeadParser(sink)
.parse(headerMetadata.getHeaderMetadata());

sink.rawText(headerMetadata.getHtml());
}


private MemoryLogHandler asciidoctorLoggingSetup(Asciidoctor asciidoctor, LogHandler logHandler, File siteDirectory) {

final MemoryLogHandler memoryLogHandler = new MemoryLogHandler(logHandler.getOutputToConsole(), siteDirectory,
Expand Down Expand Up @@ -140,9 +149,4 @@ private void requireLibrary(Asciidoctor asciidoctor, String require) {
}
}
}

protected String convertAsciiDoc(Asciidoctor asciidoctor, String source, Options options) {
return asciidoctor.convert(source, options);
}

}
Loading
Loading