Skip to content

Commit

Permalink
(v2.2.x) #763 missing breadcrumb in maven site module (#769)
Browse files Browse the repository at this point in the history
* Set document title, author(s) and date for Maven site integration

fixes #763

---------

Co-authored-by: Alexander Kriegisch <Alexander@Kriegisch.name>
  • Loading branch information
abelsromero and kriegaex committed Feb 9, 2024
1 parent 8aae0db commit 2821df1
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 121 deletions.
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);
}

}

0 comments on commit 2821df1

Please sign in to comment.