This is an automated email from the ASF dual-hosted git repository. kwin pushed a commit to branch feature/preserve-vtl-statements in repository https://gitbox.apache.org/repos/asf/maven-doxia-converter.git
commit 0892a3053e43ba626e52918b2c0ecb1e0e6c1965 Author: Konrad Windszus <k...@apache.org> AuthorDate: Tue Mar 5 19:12:13 2024 +0100 [DOXIATOOLS-84] Preserve VTL statements WIP --- pom.xml | 38 +++++ .../org/apache/maven/doxia/DefaultConverter.java | 6 + .../doxia/wrapper/PreserveVelocityStatements.java | 123 +++++++++++++++ .../java/org/apache/maven/doxia/ConverterTest.java | 20 +++ .../wrapper/PreserveVelocityStatementsTest.java | 68 +++++++++ src/test/resources/unit/apt/test.apt.vm | 166 +++++++++++++++++++++ 6 files changed, 421 insertions(+) diff --git a/pom.xml b/pom.xml index 0ede3e7..8b189f9 100644 --- a/pom.xml +++ b/pom.xml @@ -56,10 +56,22 @@ under the License. <properties> <doxiaVersion>2.0.0-M10-SNAPSHOT</doxiaVersion> + <junit5Version>5.10.2</junit5Version> <javaVersion>8</javaVersion> <project.build.outputTimestamp>2023-01-09T21:24:22Z</project.build.outputTimestamp> </properties> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.junit</groupId> + <artifactId>junit-bom</artifactId> + <version>${junit5Version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> <dependencies> <!-- doxia --> <dependency> @@ -134,6 +146,11 @@ under the License. <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-xml</artifactId> </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-velocity</artifactId> + <version>2.1.0</version> + </dependency> <dependency> <groupId>org.eclipse.sisu</groupId> <artifactId>org.eclipse.sisu.plexus</artifactId> @@ -155,6 +172,11 @@ under the License. <version>4.13.2</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> @@ -170,6 +192,22 @@ under the License. </excludes> </configuration> </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <dependencies> + <!-- execute both JUnit3/4 and JUnit5 tests --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit5Version}</version> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <version>${junit5Version}</version> + </dependency> + </dependencies> + </plugin> </plugins> </pluginManagement> <plugins> diff --git a/src/main/java/org/apache/maven/doxia/DefaultConverter.java b/src/main/java/org/apache/maven/doxia/DefaultConverter.java index 5458cd3..3dd38c7 100644 --- a/src/main/java/org/apache/maven/doxia/DefaultConverter.java +++ b/src/main/java/org/apache/maven/doxia/DefaultConverter.java @@ -47,6 +47,7 @@ import org.apache.maven.doxia.wrapper.InputFileWrapper; import org.apache.maven.doxia.wrapper.InputReaderWrapper; import org.apache.maven.doxia.wrapper.OutputFileWrapper; import org.apache.maven.doxia.wrapper.OutputStreamWrapper; +import org.apache.maven.doxia.wrapper.PreserveVelocityStatements; import org.codehaus.plexus.ContainerConfiguration; import org.codehaus.plexus.DefaultContainerConfiguration; import org.codehaus.plexus.DefaultPlexusContainer; @@ -411,6 +412,11 @@ public class DefaultConverter implements Converter { } LOGGER.debug("Sink used: {}", sink.getClass().getName()); + // is it a Velocity file + if (inputFile.getName().endsWith(".vm")) { + LOGGER.info("Preserving Velocity statements in file {}", inputFile.getPath()); + sink = new PreserveVelocityStatements(sink); + } parse(parser, reader, sink); if (formatOutput && output.getFormat().isXml()) { diff --git a/src/main/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatements.java b/src/main/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatements.java new file mode 100644 index 0000000..4fbbf97 --- /dev/null +++ b/src/main/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatements.java @@ -0,0 +1,123 @@ +/* + * 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.doxia.wrapper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.io.UncheckedIOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.sink.SinkEventAttributes; +import org.apache.maven.doxia.sink.impl.SinkWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Preserves all Velocity (VTL) statements, which are + * <ul> + * <li>comments</li> + * <li>references and</li> + * <li>directives</li> + * </ul> + * by emitting them in dedicated {@link Sink#rawText(String)} statements. + * @see <a href="https://velocity.apache.org/engine/devel/user-guide.html">Velocity - User Guide</a> + */ +public class PreserveVelocityStatements extends SinkWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(PreserveVelocityStatements.class); + + /** + * Pattern for VTL references + * @see <a href="https://velocity.apache.org/engine/devel/user-guide.html#references">Reference</a> + */ + static final Pattern REFERENCE_PATTERN = Pattern.compile("\\$([a-zA-Z](\\w)*(\\.\\w*)*)|(\\{[^\\}]*\\})"); + + // this approach does not work due to macros and directives not always at the beginning of a line + static final Set<String> VALID_DIRECTIVES = new HashSet<>(Arrays.asList( + "#set", + "#if", + "#else", + "#end", + "#foreach", + "#include", + "#parse", + "#break", + "#stop", + "#evaluate", + "#define", + "#macro")); + + public PreserveVelocityStatements(Sink delegate) { + super(delegate); + } + + @Override + public void text(String text, SinkEventAttributes attributes) { + try (BufferedReader reader = new BufferedReader(new StringReader(text))) { + String line; + boolean isFirstLine = true; + while ((line = reader.readLine()) != null) { + if (!isFirstLine) { + super.text(EOL); + } else { + isFirstLine = false; + } + processLine(line); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public void processLine(String line) { + String trimmedText = line.trim(); + if (trimmedText.startsWith("##")) { + LOGGER.debug("Found line {} being a VTL comment, emitting as raw text", line); + rawText(line); + } else if (trimmedText.startsWith("#") && VALID_DIRECTIVES.stream().anyMatch(trimmedText::startsWith)) { + LOGGER.debug("Found line {} being a VTL directive, emitting as raw text", line); + rawText(line); + } else { + Matcher matcher = REFERENCE_PATTERN.matcher(line); + int start = 0; + while (matcher.find()) { + if (start < matcher.start()) { + super.text(line.substring(start, matcher.start())); + } + String reference = line.substring(matcher.start(), matcher.end()); + LOGGER.debug("Found VTL reference {} in line {}, emitting as raw text", reference, line); + rawText(reference); + start = matcher.end(); + } + if (start == 0) { + super.text(line); + } else { + if (start < line.length() - 1) { + super.text(line.substring(start)); + } + } + } + } +} diff --git a/src/test/java/org/apache/maven/doxia/ConverterTest.java b/src/test/java/org/apache/maven/doxia/ConverterTest.java index ba4fc23..4cf0842 100644 --- a/src/test/java/org/apache/maven/doxia/ConverterTest.java +++ b/src/test/java/org/apache/maven/doxia/ConverterTest.java @@ -160,6 +160,26 @@ public class ConverterTest extends PlexusTestCase { assertTrue(new File(out).length() != 0); } + /** + * Input apt file / output file + * + * @see Converter#convert(InputFileWrapper, OutputFileWrapper) + * @throws Exception if any + */ + public void testAptVelocityFileConverter() throws Exception { + String in = getBasedir() + "/src/test/resources/unit/apt/test.apt.vm"; + String out = getBasedir() + "/target/unit/file/apt/test.md"; + + InputFileWrapper input = InputFileWrapper.valueOf(in, DoxiaFormat.APT, ReaderFactory.UTF_8); + OutputFileWrapper output = OutputFileWrapper.valueOf(out, DoxiaFormat.MARKDOWN, WriterFactory.UTF_8); + + converter.setFormatOutput(formatOutput); + converter.convert(input, output); + assertTrue(new File(out).exists()); + assertTrue(new File(out).length() != 0); + + } + /** * Input fml dir / output dir * diff --git a/src/test/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatementsTest.java b/src/test/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatementsTest.java new file mode 100644 index 0000000..bccb24c --- /dev/null +++ b/src/test/java/org/apache/maven/doxia/wrapper/PreserveVelocityStatementsTest.java @@ -0,0 +1,68 @@ +/* + * 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.doxia.wrapper; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PreserveVelocityStatementsTest { + + @Test + void testReferencePattern() { + // variables + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN.matcher("$foo").matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$mudSlinger") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$mud_slinger") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$mudSlinger1") + .matches()); + // properties + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$customer.Address") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$purchase.Total") + .matches()); + // methods + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$customer.getAddress()") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$purchase.getTotal()") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$page.setTitle( \"My Home Page\" )") + .matches()); + assertTrue(PreserveVelocityStatements.REFERENCE_PATTERN + .matcher("$person.setAttributes( [\"Strange\", \"Weird\", \"Excited\"] )") + .matches()); + // https://velocity.apache.org/engine/devel/user-guide.html#index-notation + + // https://velocity.apache.org/engine/devel/user-guide.html#formal-reference-notation + + // https://velocity.apache.org/engine/devel/user-guide.html#alternate-values + + // https://velocity.apache.org/engine/devel/user-guide.html#quiet-reference-notation + } +} diff --git a/src/test/resources/unit/apt/test.apt.vm b/src/test/resources/unit/apt/test.apt.vm new file mode 100644 index 0000000..bdddb82 --- /dev/null +++ b/src/test/resources/unit/apt/test.apt.vm @@ -0,0 +1,166 @@ + ----- + Maven Project Parent POM + ----- + Benson Margulies + Hervé Boutemy + Karl Heinz Marbaise + ----- + 2015-09-20 + ----- + +~~ 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. + +~~ NOTE: For help with the syntax of this file, see: +~~ https://maven.apache.org/doxia/references/apt-format.html + +Maven Project Parent POM + + This POM is the common parent of all of the Maven components + in the Apache Maven project. Most of its contents are + pinning down version numbers of plugins. It does + provide {{{./dependency-management.html}minimal dependencyManagement}} for + plexus-component and plugin-tools annotations. + + This POM contains Maven developers information for the {{{./team.html}Project Team report}}, + sorted by role and id. + See the LDAP extract for more accurate {{{https://people.apache.org/committers-by-project.html#maven}committers}} + and {{{https://people.apache.org/committers-by-project.html#maven-pmc}PMC members}} lists. + +* The <<<reporting>>> Profile + + This POM provides <<<reporting>>> profile for rendering documentation during site generation: + ++-----+ +mvn -Preporting site ++-----+ + + See {{{./plugins.html}Plugins report}} for a list of configured report plugins. + +* The <<<jdk-toolchain>>> Profile + + This POM provides <<<jdk-toolchain>>> profile to activate JDK selection as a toolchain with version + requirement configured as minimum java version for the project. + +* The <<<format>>> Profile + + Since version 38 the <<<format>>> profile can be used to explicitly format source files with + {{{https://github.com/diffplug/spotless/tree/main/plugin-maven}spotless-maven-plugin}} according to + {{{/developers/conventions/code.html}Maven standards}}. + This requires the phase {{{/guides/introduction/introduction-to-the-lifecycle.html#default-lifecycle}process-sources}}. + After applying bigger reformatting it is recommended to add or update a <<<.git-blame-ignore-revs>>> file in the root of the repository + containing a line with the SHA1 of the formatting commit to ignore those changes when using <<<git blame>>> (or equivalent concepts). + This is automatically considered by {{{https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#bypassing-git-blame-ignore-revs-in-the-blame-view}GitHub}} + and can optionally be considered with {{{https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt}local <<<git blame>>>}} + +* Site Publication + + This POM prepares site publication to {{{/developers/website/index.html}Apache Maven's site svnpubsub}}. + Every inheriting POM needs to define <<<maven.site.path>>> property + with relative path to <<<$\{project.artifactId}-LATEST>>> publication uri, and define <<<distributionManagement>>> to avoid + automatic inheritance from parent: + ++-----+ + <properties> + <maven.site.path>xxx-archives/\${project.artifactId}-LATEST</maven.site.path> + </properties> + <distributionManagement> + <site> + <id>apache.website</id> + <url>scm:svn:https://svn.apache.org/repos/infra/websites/production/maven/components/${maven.site.path}</url> + </site> + </distributionManagement> ++-----+ + + Once this is configured, the site can be published with: + ++-----+ +mvn -Preporting site site:stage +mvn scm-publish:publish-scm ++-----+ + + See {{{/developers/website/deploy-component-reference-documentation.html}deploying Maven components reference documentation}} + for more information. + +* History + +#if( $project.version.endsWith( "SNAPSHOT" ) ) +#**##set( $prev = 40 ) + master: {{{https://github.com/apache/maven-parent/tree/master/pom.xml}$project.version}} + ({{{https://github.com/apache/maven-parent/compare/maven-parent-$prev...master#diff}diff}}, + {{{https://github.com/apache/maven-parent/compare/maven-parent-$prev...master}commits}}) +#end +#macro ( display $version $date ) +#**##if ( $version == 30 ) #set( $prev = 27 )#else#set( $prev = $version - 1 )#end +| {{{https://github.com/apache/maven-parent/tree/maven-parent-$version/pom.xml}$version}} +| ({{{https://github.com/apache/maven-parent/compare/maven-parent-$prev...maven-parent-$version#diff}diff}}, +| {{{https://github.com/apache/maven-parent/compare/maven-parent-$prev...maven-parent-$version}commits}}) | $date | +#end + + As of version 38, this POM sets the Java source and target versions to 1.8. Thus, as any plugin (or other component) + moved to version 38+ of this POM, it moves to requiring Java 1.8 (was Java 1.5 since version 21, Java 1.6 since + version 27, and Java 1.7 since version 34). + +*--------------+------------+ +|| <<Version>> || <<Release Date>> || +*--------------+------------+ +#display( 41, '2023-11-08' ) +*--------------+------------+ +#display( 40, '2023-06-12' ) +*--------------+------------+ +#display( 39, '2022-12-11' ) +*--------------+------------+ +#display( 38, '2022-11-21' ) +*--------------+------------+ +#display( 37, '2022-07-20' ) +*--------------+------------+ +#display( 36, '2022-04-18' ) +*--------------+------------+ +#display( 35, '2022-03-02' ) +*--------------+------------+ +#display( 34, '2020-01-30' ) +*--------------+------------+ +#display( 33, '2018-09-11' ) +*--------------+------------+ +#display( 32, '2018-07-18' ) +*--------------+------------+ +#display( 31, '2018-02-05' ) +*--------------+------------+ +#display( 30, '2016-05-26' ) +*--------------+------------+ +#display( 27, '2015-09-23' ) +*--------------+------------+ +#display( 26, '2014-11-13' ) +*--------------+------------+ +#display( 25, '2014-10-22' ) +*--------------+------------+ +#display( 24, '2014-03-27' ) +*--------------+------------+ +#display( 23, '2013-01-21' ) +*--------------+------------+ +#display( 22, '2012-08-08' ) +*--------------+------------+ +#display( 21, '2011-08-18' ) +*--------------+------------+ +#display( 20, '2011-06-15' ) +*--------------+------------+ +#display( 19, '2011-02-15' ) +*--------------+------------+ +#display( 18, '2010-11-26' ) +*--------------+------------+ +#display( 17, '2010-11-04' ) +*--------------+------------+ \ No newline at end of file