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

Reply via email to