This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new e088bca1d8 issue #6295 (#6316)
e088bca1d8 is described below

commit e088bca1d81df52d84c085083a103386f71ed9b5
Author: solarflare <[email protected]>
AuthorDate: Fri Jan 9 15:06:09 2026 +0100

    issue #6295 (#6316)
    
    * issue #6295
    
    * spotless fix
    
    ---------
    
    Co-authored-by: Hans Van Akelyen <[email protected]>
---
 .../modules/ROOT/pages/hop-tools/hop-doc.adoc      | 158 +++++++++++++++++++++
 .../modules/ROOT/pages/hop-tools/index.adoc        |   1 +
 .../ROOT/pages/workflow/actions/documentation.adoc |   5 +-
 plugins/misc/documentation/pom.xml                 |  24 ++++
 .../misc/documentation/src/assembly/assembly.xml   |  12 ++
 .../org/apache/hop/documentation/ActionDoc.java    |  31 +++-
 .../org/apache/hop/documentation/DocBuilder.java   |  97 ++++++++++++-
 .../messages/messages_en_US.properties             |   2 +
 8 files changed, 323 insertions(+), 7 deletions(-)

diff --git a/docs/hop-user-manual/modules/ROOT/pages/hop-tools/hop-doc.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/hop-tools/hop-doc.adoc
new file mode 100644
index 0000000000..d8c2f784b1
--- /dev/null
+++ b/docs/hop-user-manual/modules/ROOT/pages/hop-tools/hop-doc.adoc
@@ -0,0 +1,158 @@
+////
+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 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.
+////
+:description: Hop Doc generates project documentation
+= Hop Doc
+
+Hop Doc generates documentation for Hop projects in Markdown format with 
optional HTML output.
+
+== Usage
+
+Generate documentation for a Hop project:
+
+[source,command]
+----
+./hop.bat doc -s /path/to/project -t /path/to/docs [--generate-html] 
[--remove-markdown]
+----
+
+Or using Hop project variables:
+[source,command]
+----
+./hop.bat run -j my-project doc -t /path/to/docs --generate-html
+----
+
+== Options
+
+[options="header"]
+|===
+|Option |Description |Default
+|-s, --source-folder |Source project folder to document |Required (or use 
project)
+|-t, --target-folder |Target documentation folder |Required
+|-ip, --include-parameters |Include pipeline/workflow parameters |true
+|-in, --include-notes |Include notes text |false
+|-im, --include-metadata |Include metadata overview |true
+|-n, --project-name |Project name |"Hop" (or HOP_PROJECT_NAME)
+|-gh, --generate-html |Generate HTML versions of all docs |false
+|-rmmd, --remove-markdown |Remove .md files after HTML generation |false
+|===
+
+== Examples
+
+=== Basic Documentation
+
+Generate Markdown documentation only:
+
+[tabs]
+====
+Windows::
++
+--
+[source,shell]
+----
+./hop.bat doc -s "C:\Projects\my-hop-project" -t "C:\yourLocation\docs"
+----
+
+Linux/macOS::
++
+--
+[source,shell]
+----
+./hop.sh doc -s ~/projects/my-hop-project -t ~/docs
+----
+====
+
+=== HTML Documentation
+
+Generate HTML + remove Markdown source:
+
+[tabs]
+====
+Windows::
++
+--
+[source,shell]
+----
+./hop.bat doc -s "C:\Projects\my-hop-project" -t "C:\yourLocation\docs" 
--generate-html --remove-markdown
+----
+
+Generates:
+[source]
+----
+C:\docs\
+├── index.html (project TOC)
+├── pipelines\
+│   └── my-pipeline.html
+├── workflows\
+│   └── my-workflow.html
+└── assets\
+    ├── styles.css
+    └── images\
+----
+
+Linux/macOS::
++
+--
+[source,shell]
+----
+./hop.sh doc -s ~/projects/my-hop-project -t ~/docs --generate-html 
--remove-markdown
+----
+====
+
+=== Using Hop Project Context
+
+[source,shell]
+----
+./hop.bat run -j IT-mongo doc -t "C:\yourLocation\docs" --generate-html
+----
+
+Uses `HOP_PROJECT_HOME` and `HOP_PROJECT_NAME` automatically.
+
+== Workflow Action Usage
+
+Add "Documentation" action to any Hop workflow:
+
+1. Drag **Documentation** action from Utility category
+2. Set **Target folder** (`C:\yourLocation\docs`)
+3. Optional: Check **Generate HTML**
+4. Optional: Check **Remove markdown** (only when Generate HTML enabled)
+5. Configure content options:
+   - ☑ **Include parameters** (optional)
+   - ☑ **Include metadata** (optional)
+   - ☐ **Include notes** (optional)
+
+== Generated Structure
+
+docs/
+├── index.html (Table of Contents)
+├── pipelines/ (all .hpl files)
+│ ├── pipeline1.html
+│ └── subfolder/
+│ └── pipeline2.html
+├── workflows/ (all .hwf files)
+│ └── workflow1.html
+├── metadata/ (metadata overview)
+└── assets/
+├── styles.css
+└── images/
+
+== Notes
+
+* `--remove-markdown` is **automatically disabled** if `--generate-html` is 
false
+* HTML output includes custom CSS styling and responsive images
+* All links in `index.html` automatically point to `.html` files
+* Supports nested folders and metadata documentation
+* Uses CommonMark for Markdown → HTML conversion
\ No newline at end of file
diff --git a/docs/hop-user-manual/modules/ROOT/pages/hop-tools/index.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/hop-tools/index.adoc
index 9c308af0a6..3bae65388c 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/hop-tools/index.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/hop-tools/index.adoc
@@ -28,4 +28,5 @@ This page provides an overview of the tools that are 
available in the platform.
 * xref:hop-run/index.adoc[Hop Run]
 * xref:hop-tools/hop-search.adoc[Hop Search]
 * xref:hop-tools/hop-import.adoc[Hop Import]
+* xref:hop-tools/hop-doc.adoc[Hop Documentation]
 * xref:hop-server/index.adoc[Hop Server]
diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/documentation.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/documentation.adoc
index cded00b783..3cc1f9344c 100644
--- 
a/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/documentation.adoc
+++ 
b/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/documentation.adoc
@@ -29,8 +29,11 @@ This action builds documentation of your Hop files or 
project.
 * The target folder in which you want your project documentation to end up in.
 * Include notes?
 * Include parameters?
+* Include metadata?
+* Generate HTML?
+* Remove MarkDown after HTML is generated?
 
-== Generating HTML
+== Generating HTML from MarkDown
 
 The links from the index are currently set to the .md.html files.
 I ran the following command in the target folder to generate the HTML files:
diff --git a/plugins/misc/documentation/pom.xml 
b/plugins/misc/documentation/pom.xml
index 33f4adeb03..de3b796a72 100644
--- a/plugins/misc/documentation/pom.xml
+++ b/plugins/misc/documentation/pom.xml
@@ -29,4 +29,28 @@
     <packaging>jar</packaging>
     <name>Hop Plugins Miscellaneous Documentation</name>
 
+    <properties>
+        <commonmark.version>0.27.0</commonmark.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.hop</groupId>
+                <artifactId>hop-libs</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.commonmark</groupId>
+            <artifactId>commonmark</artifactId>
+            <version>${commonmark.version}</version>
+        </dependency>
+    </dependencies>
+
 </project>
diff --git a/plugins/misc/documentation/src/assembly/assembly.xml 
b/plugins/misc/documentation/src/assembly/assembly.xml
index 858f25610d..86202c5d7e 100644
--- a/plugins/misc/documentation/src/assembly/assembly.xml
+++ b/plugins/misc/documentation/src/assembly/assembly.xml
@@ -47,5 +47,17 @@
             </includes>
             <outputDirectory>plugins/misc/documentation</outputDirectory>
         </dependencySet>
+        <dependencySet>
+            <scope>runtime</scope>
+            <excludes>
+                <exclude>commons-codec:*</exclude>
+                <exclude>commons-logging:*</exclude>
+                <exclude>org.slf4j:*</exclude>
+                <exclude>org.apache.httpcomponents:*</exclude>
+            </excludes>
+            <outputDirectory>plugins/misc/documentation/lib</outputDirectory>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useProjectArtifact>false</useProjectArtifact>
+        </dependencySet>
     </dependencySets>
 </assembly>
\ No newline at end of file
diff --git 
a/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/ActionDoc.java
 
b/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/ActionDoc.java
index 909c0e6dc3..5a1c155372 100644
--- 
a/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/ActionDoc.java
+++ 
b/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/ActionDoc.java
@@ -83,6 +83,24 @@ public class ActionDoc extends ActionBase implements 
Cloneable, IAction {
   @HopMetadataProperty
   private boolean includingMetadata = true;
 
+  @GuiWidgetElement(
+      id = "1040-action-doc-dialog-generate-Html",
+      parentId = GUI_WIDGETS_PARENT_ID,
+      type = GuiElementType.CHECKBOX,
+      variables = false,
+      label = "i18n::ActionDoc.generateHtml.Label")
+  @HopMetadataProperty
+  private boolean generateHtml = true;
+
+  @GuiWidgetElement(
+      id = "1050-action-doc-dialog-remove-markdown",
+      parentId = GUI_WIDGETS_PARENT_ID,
+      type = GuiElementType.CHECKBOX,
+      variables = false,
+      label = "i18n:ActionDoc.RemoveMarkdown.Label")
+  @HopMetadataProperty
+  private boolean removeMarkdown = false;
+
   public ActionDoc() {}
 
   public ActionDoc(ActionDoc other) {
@@ -90,6 +108,9 @@ public class ActionDoc extends ActionBase implements 
Cloneable, IAction {
     this.targetParentFolder = other.targetParentFolder;
     this.includingNotes = other.includingNotes;
     this.includingParameters = other.includingParameters;
+    this.includingMetadata = other.includingMetadata;
+    this.generateHtml = other.generateHtml;
+    this.removeMarkdown = other.removeMarkdown;
   }
 
   @Override
@@ -107,6 +128,12 @@ public class ActionDoc extends ActionBase implements 
Cloneable, IAction {
   @Override
   public Result execute(Result prevResult, int nr) {
 
+    // SAFETY CHECK: Disable removeMarkdown if generateHtml=false
+    if (removeMarkdown && !generateHtml) {
+      getLogChannel().logBasic("Remove Markdown disabled - Generate HTML not 
selected");
+      removeMarkdown = false;
+    }
+
     MultiMetadataProvider provider;
     if (getMetadataProvider() instanceof MultiMetadataProvider) {
       provider = (MultiMetadataProvider) getMetadataProvider();
@@ -124,7 +151,9 @@ public class ActionDoc extends ActionBase implements 
Cloneable, IAction {
             resolve(targetParentFolder),
             includingParameters,
             includingNotes,
-            includingMetadata);
+            includingMetadata,
+            generateHtml,
+            removeMarkdown);
     docBuilder.buildDocumentation(prevResult);
     return prevResult;
   }
diff --git 
a/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/DocBuilder.java
 
b/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/DocBuilder.java
index 29719623d2..698a8acf9f 100644
--- 
a/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/DocBuilder.java
+++ 
b/plugins/misc/documentation/src/main/java/org/apache/hop/documentation/DocBuilder.java
@@ -18,7 +18,9 @@
 
 package org.apache.hop.documentation;
 
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -43,6 +45,9 @@ import org.apache.hop.hop.plugin.HopCommand;
 import org.apache.hop.hop.plugin.IHopCommand;
 import org.apache.hop.metadata.api.IHasHopMetadataProvider;
 import org.apache.hop.metadata.serializer.multi.MultiMetadataProvider;
+import org.commonmark.node.Node;
+import org.commonmark.parser.Parser;
+import org.commonmark.renderer.html.HtmlRenderer;
 import picocli.CommandLine;
 
 @Getter
@@ -100,6 +105,16 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
       description = "The source folder to document")
   private String sourceFolder;
 
+  @CommandLine.Option(
+      names = {"-gh", "--generate-html"},
+      description = "Generate HTML versions of documentation files")
+  private boolean generateHtml;
+
+  @CommandLine.Option(
+      names = {"-rmmd", "--remove-markdown"},
+      description = "Removes markdown after generating html files")
+  private boolean removeMarkdown;
+
   public DocBuilder() {}
 
   public DocBuilder(
@@ -111,7 +126,9 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
       String targetParentFolder,
       boolean includingParameters,
       boolean includingNotes,
-      boolean includingMetadata) {
+      boolean includingMetadata,
+      boolean generateHtml,
+      boolean removeMarkdown) {
     this.log = log;
     this.variables = variables;
     this.metadataProvider = metadataProvider;
@@ -121,6 +138,8 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
     this.includingParameters = includingParameters;
     this.includingNotes = includingNotes;
     this.includingMetadata = includingMetadata;
+    this.generateHtml = generateHtml;
+    this.removeMarkdown = removeMarkdown;
   }
 
   @Override
@@ -182,7 +201,9 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
               targetParentFolder,
               includingParameters,
               includingNotes,
-              includingMetadata);
+              includingMetadata,
+              generateHtml,
+              removeMarkdown);
       docBuilder.buildDocumentation(new Result());
     } catch (Exception e) {
       log.logError("Error generating documentation", e);
@@ -220,6 +241,8 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
         }
       }
       writeToc(toc, targetParentFolder, projectName);
+      generateHtmlFromToc(toc, targetParentFolder);
+
       log.logBasic("Finished generating documentation for project " + 
projectName);
     } catch (Exception e) {
       log.logError("Error building documentation", e);
@@ -410,13 +433,77 @@ public class DocBuilder implements Runnable, IHopCommand, 
IHasHopMetadataProvide
     }
   }
 
-  public void saveFile(String svgFilename, String pipelineSvg) throws 
Exception {
-    try (OutputStream outputStream = HopVfs.getOutputStream(svgFilename, 
false)) {
-      outputStream.write(pipelineSvg.getBytes());
+  public void saveFile(String filename, String content) throws Exception {
+    try (OutputStream outputStream = HopVfs.getOutputStream(filename, false)) {
+      outputStream.write(content.getBytes());
       outputStream.flush();
     }
   }
 
+  public String readFile(String fileName) throws HopException {
+    try (InputStream inputStream = HopVfs.getInputStream(fileName)) {
+      return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
+    } catch (Exception e) {
+      throw new HopException("Unable to read file " + fileName, e);
+    }
+  }
+
+  private String markdownToHtml(String markdown) {
+    Parser parser = Parser.builder().build();
+    HtmlRenderer renderer = HtmlRenderer.builder().build();
+
+    Node document = parser.parse(markdown);
+    return renderer.render(document);
+  }
+
+  private void generateHtmlFromToc(Toc toc, String targetParentFolder) throws 
Exception {
+    log.logBasic("generateHtml flag = " + generateHtml);
+    log.logBasic("removeMarkdown flag = " + removeMarkdown);
+    if (!generateHtml) {
+      return;
+    }
+
+    // Generate index.html from index.md
+    String indexMdFile = targetParentFolder + "/" + INDEX_MD;
+    if (new java.io.File(indexMdFile).exists()) {
+      String indexMarkdown = readFile(indexMdFile);
+      String indexHtml = markdownToHtml(indexMarkdown);
+      indexHtml = indexHtml.replaceAll("\\.md([^a-zA-Z0-9])", ".html$1");
+      String indexHtmlFile = indexMdFile.replace(".md", ".html");
+      saveFile(indexHtmlFile, indexHtml);
+      log.logBasic("Generated: " + indexHtmlFile + " (with fixed links)");
+    }
+
+    // DELETE index.md if removeMarkdown flag is set
+    if (removeMarkdown) {
+      java.io.File indexFile = new java.io.File(indexMdFile);
+      if (indexFile.exists() && indexFile.delete()) {
+        log.logBasic("Deleted index markdown file: " + indexMdFile);
+      } else {
+        log.logBasic("Failed to delete index markdown file: " + indexMdFile);
+      }
+    }
+
+    // Generate other HTML files & removing the markdown if applicable
+    for (TocEntry entry : toc.getEntries()) {
+      String mdFile = targetParentFolder + "/" + entry.targetDocFile();
+      String markdown = readFile(mdFile);
+      String html = markdownToHtml(markdown);
+      String htmlFile = mdFile.replace(".md", ".html");
+      saveFile(htmlFile, html);
+      log.logBasic("Generated: " + htmlFile);
+
+      if (removeMarkdown) {
+        java.io.File file = new java.io.File(mdFile);
+        if (file.exists() && file.delete()) {
+          log.logBasic("Deleted markdown file: " + mdFile);
+        } else {
+          log.logBasic("Failed to delete markdown file (or not found): " + 
mdFile);
+        }
+      }
+    }
+  }
+
   private void processDatasetsFolder(
       Toc toc, FileObject sourceFolder, FileObject targetFolder, String 
relativeName) {}
 
diff --git 
a/plugins/misc/documentation/src/main/resources/org/apache/hop/documentation/messages/messages_en_US.properties
 
b/plugins/misc/documentation/src/main/resources/org/apache/hop/documentation/messages/messages_en_US.properties
index fdc6abcd80..aefa9535d8 100644
--- 
a/plugins/misc/documentation/src/main/resources/org/apache/hop/documentation/messages/messages_en_US.properties
+++ 
b/plugins/misc/documentation/src/main/resources/org/apache/hop/documentation/messages/messages_en_US.properties
@@ -25,3 +25,5 @@ ActionDoc.Target.Label=The target folder
 ActionDoc.Notes.Label=Include notes text?
 ActionDoc.Parameters.Label=List parameters?
 ActionDoc.Metadata.Label=Include metadata?
+ActionDoc.generateHtml.Label=Generate HTML?
+ActionDoc.RemoveMarkdown.Label=Remove MarkDown files?
\ No newline at end of file

Reply via email to