[ https://issues.apache.org/jira/browse/MPLUGIN-442?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17800373#comment-17800373 ]
ASF GitHub Bot commented on MPLUGIN-442: ---------------------------------------- kwin commented on code in PR #225: URL: https://github.com/apache/maven-plugin-tools/pull/225#discussion_r1436150361 ########## maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/GoalRenderer.java: ########## @@ -0,0 +1,526 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.plugin.plugin.report; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.MessageFormat; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet.Semantics; +import org.apache.maven.doxia.util.HtmlTools; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.EnhancedParameterWrapper; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.i18n.I18N; + +public class GoalRenderer extends AbstractPluginReportRenderer { + + /** Regular expression matching an XHTML link with group 1 = link target, group 2 = link label. */ + private static final Pattern HTML_LINK_PATTERN = Pattern.compile("<a href=\\\"([^\\\"]*)\\\">(.*?)</a>"); + + /** The directory where the generated site is written. Used for resolving relative links to javadoc. */ + private final File reportOutputDirectory; + + private final MojoDescriptor descriptor; + private final boolean disableInternalJavadocLinkValidation; + + private final Log log; + + public GoalRenderer( + Sink sink, + I18N i18n, + Locale locale, + MavenProject project, + MojoDescriptor descriptor, + File reportOutputDirectory, + boolean disableInternalJavadocLinkValidation, + Log log) { + super(sink, locale, i18n, project); + this.reportOutputDirectory = reportOutputDirectory; + this.descriptor = descriptor; + this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation; + this.log = log; + } + + @Override + public String getTitle() { + return descriptor.getFullGoalName(); + } + + @Override + protected void renderBody() { + startSection(descriptor.getFullGoalName()); + renderReportNotice(); + renderDescription("fullname", descriptor.getPluginDescriptor().getId() + ":" + descriptor.getGoal(), false); + + String context = "goal " + descriptor.getGoal(); + if (StringUtils.isNotEmpty(descriptor.getDeprecated())) { + renderDescription("deprecated", getXhtmlWithValidatedLinks(descriptor.getDeprecated(), context), true); + } + if (StringUtils.isNotEmpty(descriptor.getDescription())) { + renderDescription("description", getXhtmlWithValidatedLinks(descriptor.getDescription(), context), true); + } else { + renderDescription("description", getI18nString("nodescription"), false); + } + renderAttributes(); + + List<Parameter> parameterList = filterParameters( + descriptor.getParameters() != null ? descriptor.getParameters() : Collections.emptyList()); + if (parameterList.isEmpty()) { + startSection(getI18nString("parameters")); + sink.paragraph(); + sink.text(getI18nString("noParameter")); + sink.paragraph_(); + endSection(); + } else { + renderParameterOverviewTable( + getI18nString("requiredParameters"), + parameterList.stream().filter(Parameter::isRequired).iterator()); + renderParameterOverviewTable( + getI18nString("optionalParameters"), + parameterList.stream().filter(p -> !p.isRequired()).iterator()); + renderParameterDetails(parameterList.iterator()); + } + endSection(); + } + + /** Filter parameters to only retain those which must be documented, i.e. neither components nor read-only ones. + * + * @param parameterList not null + * @return the parameters list without components. */ + private static List<Parameter> filterParameters(Collection<Parameter> parameterList) { + return parameterList.stream() + .filter(p -> p.isEditable() + && (p.getExpression() == null || !p.getExpression().startsWith("${component."))) + .collect(Collectors.toList()); + } + + private void renderReportNotice() { + if (PluginUtils.isMavenReport(descriptor.getImplementation(), project)) { + renderDescription("notice.prefix", getI18nString("notice.isMavenReport"), false); + } + } + + /** + * A description consists of a term/prefix and the actual description text + */ + private void renderDescription(String prefixKey, String description, boolean isHtmlMarkup) { + // TODO: convert to dt and dd elements + renderDescriptionPrefix(prefixKey); + sink.paragraph(); + if (isHtmlMarkup) { + sink.rawText(description); + } else { + sink.text(description); + } + sink.paragraph_(); // p + } + + private void renderDescriptionPrefix(String prefixKey) { + sink.paragraph(); + sink.inline(Semantics.STRONG); + sink.text(getI18nString(prefixKey)); + sink.inline_(); + sink.text(":"); + sink.paragraph_(); + } + + @SuppressWarnings("deprecation") + private void renderAttributes() { + renderDescriptionPrefix("attributes"); + sink.list(); + + renderAttribute(descriptor.isProjectRequired(), "projectRequired"); + renderAttribute(descriptor.isRequiresReports(), "reportingMojo"); + renderAttribute(descriptor.isAggregator(), "aggregator"); + renderAttribute(descriptor.isDirectInvocationOnly(), "directInvocationOnly"); + renderAttribute(descriptor.isDependencyResolutionRequired(), "dependencyResolutionRequired"); + + if (descriptor instanceof ExtendedMojoDescriptor) { + ExtendedMojoDescriptor extendedDescriptor = (ExtendedMojoDescriptor) descriptor; + renderAttribute(extendedDescriptor.getDependencyCollectionRequired(), "dependencyCollectionRequired"); + } + + renderAttribute(descriptor.isThreadSafe(), "threadSafe"); + renderAttribute(!descriptor.isThreadSafe(), "notThreadSafe"); + renderAttribute(descriptor.getSince(), "since"); + renderAttribute(descriptor.getPhase(), "phase"); + renderAttribute(descriptor.getExecutePhase(), "executePhase"); + renderAttribute(descriptor.getExecuteGoal(), "executeGoal"); + renderAttribute(descriptor.getExecuteLifecycle(), "executeLifecycle"); + renderAttribute(descriptor.isOnlineRequired(), "onlineRequired"); + renderAttribute(!descriptor.isInheritedByDefault(), "notInheritedByDefault"); + + sink.list_(); + } + + private void renderAttribute(boolean condition, String attributeKey) { + renderAttribute(condition, attributeKey, Optional.empty()); + } + + private void renderAttribute(String conditionAndCodeArgument, String attributeKey) { + renderAttribute( + StringUtils.isNotEmpty(conditionAndCodeArgument), + attributeKey, + Optional.ofNullable(conditionAndCodeArgument)); + } + + private void renderAttribute(boolean condition, String attributeKey, Optional<String> codeArgument) { + if (condition) { + sink.listItem(); + linkPatternedText(getI18nString(attributeKey)); + if (codeArgument.isPresent()) { + text(": "); + sink.inline(Semantics.CODE); + sink.text(codeArgument.get()); + sink.inline_(); + } + text("."); + sink.listItem_(); + } + } + + private void renderParameterOverviewTable(String title, Iterator<Parameter> parameters) { + // don't emit empty tables + if (!parameters.hasNext()) { + return; + } + startSection(title); + startTable(); + tableHeader(new String[] { + getI18nString("parameter.name.header"), + getI18nString("parameter.type.header"), + getI18nString("parameter.since.header"), + getI18nString("parameter.description.header") + }); + while (parameters.hasNext()) { + renderParameterOverviewTableRow(parameters.next()); + } + endTable(); + endSection(); + } + + private void renderTableCellWithCode(String text) { + renderTableCellWithCode(text, Optional.empty()); + } + + private void renderTableCellWithCode(String text, Optional<String> link) { + sink.tableCell(); + if (link.isPresent()) { + sink.link(link.get(), null); + } + sink.inline(Semantics.CODE); + sink.text(text); + sink.inline_(); + if (link.isPresent()) { + sink.link_(); + } + sink.tableCell_(); + } + + private void renderParameterOverviewTableRow(Parameter parameter) { + sink.tableRow(); + // name + // link to appropriate section + renderTableCellWithCode( + format("parameter.name", parameter.getName()), + // no need for additional URI encoding as it returns only URI safe characters + Optional.of("#" + HtmlTools.encodeId(parameter.getName()))); + + // type + Map.Entry<String, Optional<String>> type = getLinkedType(parameter, true); + renderTableCellWithCode(type.getKey(), type.getValue()); + + // since + String since = StringUtils.defaultIfEmpty(parameter.getSince(), "-"); + renderTableCellWithCode(since); + + // description + sink.tableCell(); + String description; + String context = "Parameter " + parameter.getName() + " in goal " + descriptor.getGoal(); + if (StringUtils.isNotEmpty(parameter.getDeprecated())) { + String deprecated = getXhtmlWithValidatedLinks(parameter.getDescription(), context); + description = format("parameter.deprecated", deprecated); Review Comment: That is a copy-paste mistake. > Rewrite plugin goal documentation generation to use supplied sink instead of > direct Xdoc > ---------------------------------------------------------------------------------------- > > Key: MPLUGIN-442 > URL: https://issues.apache.org/jira/browse/MPLUGIN-442 > Project: Maven Plugin Tools > Issue Type: Improvement > Components: Plugin Plugin > Reporter: Konrad Windszus > Assignee: Konrad Windszus > Priority: Major > Fix For: 3.10.0, 3.10.1 > > > At some time in the future m-site-p/doxia will no longer support XDoc > (compare with > https://issues.apache.org/jira/browse/DOXIA-569?focusedCommentId=17634481&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17634481). > Therefore the "report" goal should be converted to create "markdown" for the > plugin goal documentation pages instead of "XDoc" in > https://github.com/apache/maven-plugin-tools/blob/master/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java. -- This message was sent by Atlassian Jira (v8.20.10#820010)