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