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

paulk-asert pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 08b9f3d  add wire-car inspired example
08b9f3d is described below

commit 08b9f3d1e3e9cd2de55725f09e1af7e15d98f2ea
Author: Paul King <[email protected]>
AuthorDate: Tue May 26 20:08:36 2026 +1000

    add wire-car inspired example
---
 generator/build.gradle                             |  4 +++
 .../src/main/groovy/generator/SiteGenerator.groovy | 39 +++++++++++++++++++---
 site/src/site/pages/blog.groovy                    | 11 +++++-
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/generator/build.gradle b/generator/build.gradle
index d0a1a20..6768b51 100644
--- a/generator/build.gradle
+++ b/generator/build.gradle
@@ -41,6 +41,10 @@ dependencies {
         //exclude(group: 'org.jruby', module: 'jruby-complete')
     }
     implementation "org.asciidoctor:asciidoctorj-diagram:$asciidoctorDiagram"
+    // asciidoctorj-diagram brings asciidoctorj-diagram-plantuml in at
+    // runtime scope (versioned per PlantUML release, e.g. 1.2023.13 for
+    // diagram 2.2.17), so [plantuml,…] blocks render without depending
+    // on an external plantuml CLI being installed on the build machine.
     //compile "org.jruby:jruby-complete:9.1.17.0"
 }
 
diff --git a/generator/src/main/groovy/generator/SiteGenerator.groovy 
b/generator/src/main/groovy/generator/SiteGenerator.groovy
index fe5fd70..af644b9 100644
--- a/generator/src/main/groovy/generator/SiteGenerator.groovy
+++ b/generator/src/main/groovy/generator/SiteGenerator.groovy
@@ -30,7 +30,9 @@ import model.Page
 import model.Section
 import model.SectionItem
 import model.SiteMap
+import org.asciidoctor.Attributes
 import org.asciidoctor.Options
+import org.asciidoctor.SafeMode
 import org.asciidoctor.ast.Document
 
 import java.nio.file.FileSystems
@@ -272,12 +274,10 @@ class SiteGenerator {
         Map<String, Document> blogList = [:]
         Map<String, String> contents = [:]
         Map<String, String> baseDirs = [:]
-        def options = Options.builder().build()
+        Map<String, String> imageDirs = [:]
         blogDir.eachFileRecurse { f ->
             if (f.name.endsWith('.adoc')) {
                 def bn = f.name.substring(0, f.name.lastIndexOf('.adoc'))
-                def doc = asciidoctor.loadFile(f, options)
-                println "Rendering $bn"
                 def relativePath = []
                 def p = f.parentFile
                 while (p != blogDir) {
@@ -285,9 +285,35 @@ class SiteGenerator {
                     p = p.parentFile
                 }
                 String baseDir = relativePath ? 
"blog${File.separator}${relativePath.join(File.separator)}" : 'blog'
+                // asciidoctor-diagram extensions fire during loadFile
+                // (parse) as well as during the later convert() call.
+                // Without imagesoutdir set here, generated images and
+                // their .cache sidecars land next to the .adoc source
+                // file. Setting it on the loadFile options keeps the
+                // source tree clean; the convert() call below also
+                // sets it (via the blog.groovy template) so the actual
+                // <img> reference resolves at output time.
+                def blogImgDir = new File(outputDir, baseDir + File.separator 
+ 'img')
+                blogImgDir.mkdirs()
+                def attrs = Attributes.builder()
+                        .attribute('imagesoutdir', blogImgDir.absolutePath)
+                        .attribute('imagesdir', 'img')
+                        .build()
+                // SafeMode.UNSAFE lets asciidoctor-diagram write to
+                // imagesoutdir even though it's outside the source-file
+                // jail. Without this, safe mode rejects the absolute
+                // path and recovers by writing the image + .cache file
+                // next to the .adoc source — polluting the source tree.
+                def options = Options.builder()
+                        .safe(SafeMode.UNSAFE)
+                        .attributes(attrs)
+                        .build()
+                def doc = asciidoctor.loadFile(f, options)
+                println "Rendering $bn"
                 blogList[bn] = doc
                 contents[bn] = f.getText('utf-8')
                 baseDirs[bn] = baseDir
+                imageDirs[bn] = blogImgDir.absolutePath
             }
         }
         Map<String, Set> keywords = [:]
@@ -307,7 +333,12 @@ class SiteGenerator {
         }
         blogList.keySet().each { bn ->
             def sorted = related[bn].findAll { it.value as int > 1 }.sort { 
it.value }.keySet().toList().reverse()
-            render 'blog', bn, [notes: contents[bn], doc: blogList[bn], 
related: sorted.collectEntries { [it, blogList[it].structuredDoctitle.combined] 
}], baseDirs[bn]
+            render 'blog', bn, [
+                    notes: contents[bn],
+                    doc: blogList[bn],
+                    related: sorted.collectEntries { [it, 
blogList[it].structuredDoctitle.combined] },
+                    imagesoutdir: imageDirs[bn]
+            ], baseDirs[bn]
         }
         render 'blogs', "index", [list: blogList], 'blog'
         renderBlogFeed blogList, 'blog'
diff --git a/site/src/site/pages/blog.groovy b/site/src/site/pages/blog.groovy
index d66eaa1..ec88a54 100644
--- a/site/src/site/pages/blog.groovy
+++ b/site/src/site/pages/blog.groovy
@@ -6,6 +6,7 @@ modelTypes = {
     String title
     String notes
     Map<String, String> related
+    String imagesoutdir
 }
 
 title = doc.structuredDoctitle.combined
@@ -26,7 +27,15 @@ layout 'layouts/main.groovy', true,
             script { yieldUnescaped 
"document.addEventListener('DOMContentLoaded',prettyPrint)" }
         },
         mainContent: contents {
-            Map options = [attributes:[DOCS_BASEURL:DocUtils.DOCS_BASEURL]]
+            // imagesoutdir + imagesdir let asciidoctor-diagram write
+            // generated images (e.g. from [plantuml,…] blocks) into
+            // blog/img/ and emit relative `img/…` references that
+            // match the convention used for pre-rendered blog images.
+            Map options = [attributes:[
+                    DOCS_BASEURL: DocUtils.DOCS_BASEURL,
+                    imagesoutdir: imagesoutdir,
+                    imagesdir   : 'img'
+            ]]
             def notesAsHTML = asciidocText(notes,options)
             def matcher = notesAsHTML =~ /<h2 id="(.+?)">(.+?)<\/h2>/
             def sections = [:]

Reply via email to