Sorry... the commend / my description was a bit incorrect (the code is still 
identical).

Attached is the better one and here is the changed description:

---------------------------------------------------------------

Refactor org-babel-plantuml-make-body to properly parse and preserve
content around PlantUML diagram blocks.

Previously, the function would apply variable expansion to the entire
body content and only check for @start prefix to decide whether to
wrap with @startuml/@enduml tags.

Changes:

- Parse body into 5 components: prologue, start tag, inner content,
end tag, and epilogue
- Only apply variable expansion to the inner diagram content, not
the entire body
- Require exact matching between @start<type> and @end<type> tags
(e.g., @startuml must pair with @enduml, not @endsalt)
- If @start<type> exists but no matching @end<type> is found, treat
the entire body as diagram content and wrap with default tags
- Preserve any content before the first @start tag (prologue) and
after the last @end tag (epilogue) without modification
(exception: trimming)

This ensures variable substitution only affects the actual diagram content.

Examples now supported:

- Content before/after diagram blocks
- Proper handling of mismatched start/end tag pairs

---------------------------------------------------------------

On 29 Sep 2025, at 18:24, Tim Hansinger wrote:

> Hello Rudy,
>
> here's the new patch. I tried to add all your suggestions and advanced 
> handling of prologue/epilogue to it.
>
> I wrote the code in a way that no variables are redefined (all variables are 
> defined only once - as if they are "immutable" - in case you don't want that 
> I can rewrite the code which would make it a bit shorter ... but actually I 
> prefer it as it is in the patch now for better clarity).
>
> Let me know what you think.
>
> Also: The test contains a prologue/epilogue comment (meaning a comment 
> before/after the surrounding @startXXX @endXXX clause).
>
> Best
> Tim
>
> ---------------------------------------------------------------
>
> Refactor org-babel-plantuml-make-body to properly parse and preserve
> content around PlantUML diagram blocks.
>
> Previously, the function would apply variable expansion to the entire
> body content and only check for @start prefix to decide whether to
> wrap with @startuml/@enduml tags.
>
> Changes:
>
> - Parse body into 5 components: prologue, start tag, inner content,
> end tag, and epilogue
> - Only apply variable expansion to the inner diagram content, not
> the entire body
> - Require exact matching between @start<type> and @end<type> tags
> (e.g., @startuml must pair with @enduml, not @endsalt)
> - If @start<type> exists but no matching @end<type> is found, treat
> the entire body as diagram content and wrap with default tags
> - Preserve any content before the first @start tag (prologue) and
> after the last @end tag (epilogue) without modification
> (exception: trimming)
>
> This allows for more complex PlantUML source blocks that may contain
> configuration directives, comments, or multiple diagram types while
> ensuring variable substitution only affects the actual diagram content.
>
> Examples now supported:
>
> - Content before/after diagram blocks
> - Multiple diagram types (e.g. @startsalt/@endsalt, @startmindmap/@endmindmap)
> - Proper handling of mismatched start/end tag pairs
>
> ---------------------------------------------------------------
>
> On 28 Sep 2025, at 17:05, Rudolf Adamkovič wrote:
>
>> Tim Hansinger [email protected] writes:
>>
>>> Everything's clear now. I'm travelling this weekend but will have time
>>> to implement this next week.
>>
>> Thanks for the heads-up, Tim!
>>
>> As Ihor says, we are in no hurry here. :)
>>
>> In the meantime, enjoy the travels!
>>
>> Rudy
>>
>> "I have only made this letter longer because I have not had the time to
>> make it shorter." --- Blaise Pascal, The Provincial Letters, 1657
>>
>> Rudolf Adamkovič [email protected] [he/him]
>> http://adamkovic.org
From 2fdce234d2240ff21dcb650a6931c650a8a94e22 Mon Sep 17 00:00:00 2001
From: Tim Hansinger <[email protected]>
Date: Mon, 15 Sep 2025 17:52:15 +0200
Subject: [PATCH] ob-plantuml.el: Fix body parsing to handle @start/@end
 content

* lisp/ob-plantuml.el (org-babel-plantuml-make-body):
Refactor org-babel-plantuml-make-body to properly parse and preserve
content around PlantUML diagram blocks.

Previously, the function would apply variable expansion to the entire
body content and only check for @start prefix to decide whether to
wrap with @startuml/@enduml tags.

Changes:
- Parse body into 5 components: prologue, start tag, inner content,
  end tag, and epilogue
- Only apply variable expansion to the inner diagram content, not
  the entire body
- Require exact matching between @start<type> and @end<type> tags
  (e.g., @startuml must pair with @enduml, not @endsalt)
- If @start<type> exists but no matching @end<type> is found, treat
  the entire body as diagram content and wrap with default tags
- Preserve any content before the first @start tag (prologue) and
  after the last @end tag (epilogue) without modification
  (exception: trimming)

This ensures variable substitution only affects the actual diagram
content.

Examples now supported:
- Content before/after diagram blocks
- Proper handling of mismatched start/end tag pairs

* testing/lisp/test-ob-plantuml.el
(test-ob-plantuml/single-var-on-body-with-start-end-clauses-and-prologue-epilogue):
Added an additional test for aboves use case (var definition on a BODY
with pre-existing @startxxx ... @endxxx clauses and prologue / epilogue 
comments).

Reported-by: "Tim Hansinger" <[email protected]>
Link: 
https://list.orgmode.org/[email protected]/
---
 lisp/ob-plantuml.el              | 60 +++++++++++++++++++++++++++-----
 testing/lisp/test-ob-plantuml.el | 30 ++++++++++++++++
 2 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/lisp/ob-plantuml.el b/lisp/ob-plantuml.el
index 05a4f7263..48e61a741 100644
--- a/lisp/ob-plantuml.el
+++ b/lisp/ob-plantuml.el
@@ -95,20 +95,64 @@ are expected to be scalar variables."
 
 (defun org-babel-plantuml-make-body (body params)
   "Return PlantUML input string.
-
 BODY is the content of the source block and PARAMS is a property list
 of source block parameters.  This function relies on the
 `org-babel-expand-body:generic' function to extract `:var' entries
 from PARAMS and on the `org-babel-variable-assignments:plantuml'
 function to convert variables to PlantUML assignments.
 
-If BODY does not contain @startXXX ... @endXXX clauses, @startuml
-... @enduml will be added."
-  (let ((full-body
-        (org-babel-expand-body:generic
-         body params (org-babel-variable-assignments:plantuml params))))
-    (if (string-prefix-p "@start" body t) full-body
-      (format "@startuml\n%s\n@enduml" full-body))))
+The function parses BODY to find matching @startXXX ... @endXXX pairs:
+- If a matching pair is found (e.g., @startuml/@enduml or @startsalt/@endsalt),
+  variable expansion is applied only to the content between the tags,
+  preserving any prologue and epilogue content outside the tags.
+- If @startXXX is found but no matching @endXXX, or if no @startXXX is found,
+  the entire BODY is treated as diagram content and wrapped with
+  @startuml ... @enduml tags after variable expansion."
+  (let* (
+         (default-start "@startuml")
+         (default-end "@enduml")
+         (start-regex "^[[:blank:]]*@start\\([a-zA-Z]+\\)[[:blank:]]*$")
+         (start-match-pos (string-match start-regex body))
+         (start-match-end (when start-match-pos
+                            (match-end 0)))
+         (start-type (when start-match-pos 
+                       (progn (string-match start-regex body start-match-pos)
+                              (match-string 1 body))))
+         (end-regex (when start-type
+                      (format "^[[:blank:]]*@end%s\\(?:[[:blank:]]*$\\)" 
start-type)))
+         (end-match-pos (when end-regex
+                          (string-match end-regex body start-match-end)))
+         (end-match-end (when end-match-pos
+                          (match-end 0)))
+         pro epi start end wrapped-body expanded-body)
+    
+    (if (and start-match-pos end-match-pos)
+        (progn
+          ;; Extract parts when matching @start/@end pair exists and trim 
whitespace
+          (setq pro (string-trim (substring body 0 start-match-pos))
+                start (string-trim (substring body start-match-pos 
start-match-end))
+                wrapped-body (string-trim (substring body start-match-end 
end-match-pos))
+                end (string-trim (substring body end-match-pos end-match-end))
+                epi (string-trim (substring body end-match-end))
+                expanded-body (org-babel-expand-body:generic wrapped-body
+                                                             params
+                                                             
(org-babel-variable-assignments:plantuml params))))
+      ;; No @start found OR @start found but no matching @end
+      (setq expanded-body (org-babel-expand-body:generic (string-trim body)
+                                                         params
+                                                         
(org-babel-variable-assignments:plantuml params))))
+    
+    (if wrapped-body
+        (string-join (remove "" (list pro
+                                      start
+                                      expanded-body
+                                      end
+                                      epi))
+                     "\n")
+      (string-join (remove "" (list default-start
+                                    expanded-body
+                                    default-end))
+                   "\n"))))
 
 (defun org-babel-execute:plantuml (body params)
   "Execute a block of plantuml code with org-babel.
diff --git a/testing/lisp/test-ob-plantuml.el b/testing/lisp/test-ob-plantuml.el
index b45d38be6..b237be803 100644
--- a/testing/lisp/test-ob-plantuml.el
+++ b/testing/lisp/test-ob-plantuml.el
@@ -45,6 +45,36 @@ class CLASSNAME
           (car src-block-info)
           (car (cdr src-block-info)))))))))
 
+(ert-deftest 
test-ob-plantuml/single-var-on-body-with-start-end-clauses-and-prologue-epilogue
 ()
+  "Test file output with input variable on BODY with @startxxx ... @endxxx 
clauses
+and prologue / epilogue comments."
+  (should
+   (string=
+    "'prologue comment
+@startuml
+!define CLASSNAME test_class
+class CLASSNAME
+@enduml
+'epilogue comment"
+    (let ((org-plantuml-jar-path nil))
+      (org-test-with-temp-text
+         "#+name: variable_value
+: test_class
+
+#+header: :file tmp.puml
+#+header: :var CLASSNAME=variable_value
+#+begin_src plantuml
+'prologue comment
+@startuml
+class CLASSNAME
+@enduml
+'epilogue comment
+#+end_src"
+        (org-babel-next-src-block)
+       (let ((src-block-info (cdr (org-babel-get-src-block-info))))
+         (org-babel-plantuml-make-body
+          (car src-block-info)
+          (car (cdr src-block-info)))))))))
 
 (ert-deftest test-ob-plantuml/prologue ()
   "Test file output with prologue."
-- 
2.51.0

Reply via email to