diff --git a/CHANGELOG.md b/CHANGELOG.md
index 03c37bafa..80d00a7b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- new built-in function stringToBase64
+
### Changed
- fj-doc-maven-plugin, init, flavour : quarkus-version set to 3.29.2 across all the modules
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt
index c4b4845df..3ac65461c 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Background.kt
@@ -10,8 +10,8 @@ class Background : HelperDSL.TagWithText( "background" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt
index 056c3efb9..f4248d7f4 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Body.kt
@@ -31,8 +31,8 @@ class Body : HelperDSL.TagWithText( "body" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt
index 85f44df26..02d451875 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Cell.kt
@@ -24,8 +24,8 @@ class Cell : HelperDSL.TagWithText( "cell" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt
index cbdd2fdab..2dac1a94b 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Footer.kt
@@ -17,8 +17,8 @@ class Footer : HelperDSL.TagWithText( "footer" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt
index d0e71d154..25d983109 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/FooterExt.kt
@@ -24,8 +24,8 @@ class FooterExt : HelperDSL.TagWithText( "footer-ext" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt
index e880f3048..8dbdd760b 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Header.kt
@@ -17,8 +17,8 @@ class Header : HelperDSL.TagWithText( "header" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt
index 19cb10189..699834215 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/HeaderExt.kt
@@ -24,8 +24,8 @@ class HeaderExt : HelperDSL.TagWithText( "header-ext" ) {
* Creates a new default Image instance.
* @return the new instance.
*/
- fun image( init: Image.() -> Unit = {} ): Image {
- return initTag(Image(), init);
+ fun image( text: String = "", init: Image.() -> Unit = {} ): Image {
+ return initTag(Image(text), init);
}
/**
* Creates a new default Phrase instance.
diff --git a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt
index c29d7fcbb..cfcd5495a 100644
--- a/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt
+++ b/fj-doc-base-kotlin/src/main/java/org/fugerit/java/doc/base/kotlin/dsl/Image.kt
@@ -5,7 +5,15 @@ package org.fugerit.java.doc.base.kotlin.dsl
*
* This class will provide function to handle all image attributes and kids
*/
-class Image : HelperDSL.TagWithText( "image" ) {
+class Image( text: String = "" ) : HelperDSL.TagWithText( "image" ) {
+
+ init { setText(text) }
+ /**
+ * Function to set text content for this element.
+ */
+
+ fun setText( value: String ) { addKid( HelperDSL.TextElement( value ) ) }
+
/**
* Function handling url attribute of the Image with specific check on type.
diff --git a/fj-doc-base/src/main/docs/doc_xsd_config_ref.html b/fj-doc-base/src/main/docs/doc_xsd_config_ref.html
index 369654e89..e69ec17d5 100644
--- a/fj-doc-base/src/main/docs/doc_xsd_config_ref.html
+++ b/fj-doc-base/src/main/docs/doc_xsd_config_ref.html
@@ -410,6 +410,7 @@
Reference xsd documentation for Venus - Fugerit
An image to include in the document (roughly comparable to a HTML 'image' element)
|
+ mixed
|
diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocImage.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocImage.java
index 3eb14b37b..c61f9e19d 100644
--- a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocImage.java
+++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/model/DocImage.java
@@ -31,6 +31,7 @@ The Apache Software Foundation (http://www.apache.org/).
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
@@ -82,7 +83,9 @@ public static Collection getAcceptedImageTypes() {
@Getter @Setter private String alt;
@Getter @Setter private int align;
-
+
+ @Getter @Setter private String content = "";
+
public String getResolvedBase64() {
return SafeFunction.get( () -> {
String res = this.getBase64();
@@ -94,7 +97,13 @@ public String getResolvedBase64() {
}
public String getResolvedText() {
- return SafeFunction.get( () -> new String( resolveImage( this ) ) );
+ return SafeFunction.get( () -> {
+ if ( StringUtils.isEmpty( this.content ) ) {
+ return new String( resolveImage( this ) );
+ } else {
+ return this.content;
+ }
+ });
}
public String getResolvedType() {
@@ -134,6 +143,8 @@ public static byte[] resolveImage( DocImage img ) throws IOException {
data = Base64Helper.decodeBase64String( base64 );
} else if ( path != null ) {
data = byteResolverHelper( path );
+ } else if ( StringUtils.isNotEmpty( img.getContent() ) ) {
+ data = img.getContent().getBytes( StandardCharsets.UTF_8 );
} else {
throw new IOException( "Null path provided!" );
}
diff --git a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocParserContext.java b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocParserContext.java
index 29d33c762..4e432c981 100644
--- a/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocParserContext.java
+++ b/fj-doc-base/src/main/java/org/fugerit/java/doc/base/parser/DocParserContext.java
@@ -120,6 +120,9 @@ public void handleText( String text ) {
} else if ( this.currentElement instanceof DocInfo ) {
DocInfo docInfo = (DocInfo)this.currentElement;
docInfo.getContent().append( text );
+ } else if ( this.currentElement instanceof DocImage ) {
+ DocImage docImage = (DocImage)this.currentElement;
+ docImage.setContent( docImage.getContent()+text );
}
}
}
diff --git a/fj-doc-base/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-base/reflect-config.json b/fj-doc-base/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-base/reflect-config.json
index 399864159..30b81b6e6 100644
--- a/fj-doc-base/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-base/reflect-config.json
+++ b/fj-doc-base/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-base/reflect-config.json
@@ -1140,6 +1140,9 @@
}, {
"name" : "getClass",
"parameterTypes" : [ ]
+ }, {
+ "name" : "getContent",
+ "parameterTypes" : [ ]
}, {
"name" : "getId",
"parameterTypes" : [ ]
@@ -1188,6 +1191,9 @@
}, {
"name" : "setBase64",
"parameterTypes" : [ "java.lang.String" ]
+ }, {
+ "name" : "setContent",
+ "parameterTypes" : [ "java.lang.String" ]
}, {
"name" : "setId",
"parameterTypes" : [ "java.lang.String" ]
diff --git a/fj-doc-base/src/main/resources/config/doc-2-1.xsd b/fj-doc-base/src/main/resources/config/doc-2-1.xsd
index e6817940b..177a21b3b 100644
--- a/fj-doc-base/src/main/resources/config/doc-2-1.xsd
+++ b/fj-doc-base/src/main/resources/config/doc-2-1.xsd
@@ -6,7 +6,7 @@
*
* @project : fj-doc-base
* @creation : 2023-08-18
- * @version : 2.1.0-rc.3 (2025-03-22)
+ * @version : 2.1.0-rc.4 (2025-11-19)
*
* XSD for fugerit doc configuration
*/
@@ -408,7 +408,7 @@
An image to include in the document
(roughly comparable to a HTML 'image' element)
-
+
diff --git a/fj-doc-base/src/test/java/test/org/fugerit/java/doc/base/model/TestDocImage.java b/fj-doc-base/src/test/java/test/org/fugerit/java/doc/base/model/TestDocImage.java
index 0981dbbec..0b04565bc 100644
--- a/fj-doc-base/src/test/java/test/org/fugerit/java/doc/base/model/TestDocImage.java
+++ b/fj-doc-base/src/test/java/test/org/fugerit/java/doc/base/model/TestDocImage.java
@@ -6,11 +6,13 @@
import lombok.extern.slf4j.Slf4j;
+import java.io.IOException;
+
@Slf4j
class TestDocImage extends HelperDocT {
@Test
- void testElement1() {
+ void testElement1() throws IOException {
DocImage image = new DocImage();
image.setUrl( DocImage.TYPE_JPG );
Assertions.assertEquals( DocImage.TYPE_JPG, image.getResolvedType() );
@@ -22,6 +24,12 @@ void testElement1() {
image.setUrl( "cl://txt/test.txt" );
Assertions.assertEquals( "test text", image.getResolvedText() );
log.info( "accepted types : {}", DocImage.getAcceptedImageTypes() );
+ String altTest = "alt test";
+ image.setContent( altTest );
+ Assertions.assertEquals( altTest, image.getResolvedText() );
+ image.setUrl( null );
+ image.setBase64( null );
+ Assertions.assertEquals( altTest.length(), DocImage.resolveImage( image ).length );
}
}
diff --git a/fj-doc-base/src/test/resources/coverage/template/macro/html_element.ftl b/fj-doc-base/src/test/resources/coverage/template/macro/html_element.ftl
index 4beb610b4..9833be9da 100644
--- a/fj-doc-base/src/test/resources/coverage/template/macro/html_element.ftl
+++ b/fj-doc-base/src/test/resources/coverage/template/macro/html_element.ftl
@@ -55,8 +55,8 @@
<#if docImage.align = 2>
<#assign imageAlign="style='display: block; margin-left: auto; margin-right: auto;'"/>
#if>
- #if>
-
${imageAlign!''} <#if (docImage.alt)??> alt="${docImage.alt}" #if> ${imageScaling} src="data:image/png;base64, ${docImage.resolvedBase64}" />
+ #if>
+
${imageAlign!''} <#if (docImage.alt)??> alt="${docImage.alt}" #if> ${imageScaling} src="data:image/png;base64, <#if docImage.content?has_content>${docImage.content}<#else>${docImage.resolvedBase64}#if>" />
#macro>
<#macro handleList docList>
diff --git a/fj-doc-base/src/test/resources/coverage/xml/default_doc.xml b/fj-doc-base/src/test/resources/coverage/xml/default_doc.xml
index 2ae032f76..ae4f18876 100644
--- a/fj-doc-base/src/test/resources/coverage/xml/default_doc.xml
+++ b/fj-doc-base/src/test/resources/coverage/xml/default_doc.xml
@@ -40,7 +40,7 @@
-
+
| Name |
Surname |
diff --git a/fj-doc-base/src/test/resources/coverage/xml/default_doc_alt.xml b/fj-doc-base/src/test/resources/coverage/xml/default_doc_alt.xml
index fc70804a2..a75a12a39 100644
--- a/fj-doc-base/src/test/resources/coverage/xml/default_doc_alt.xml
+++ b/fj-doc-base/src/test/resources/coverage/xml/default_doc_alt.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://javacoredoc.fugerit.org https://www.fugerit.org/data/java/doc/xsd/doc-2-1.xsd" >
@@ -29,7 +29,9 @@
My sample title
-
+ ]]>
+
+
| Name |
Surname |
diff --git a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerConfigStep.java b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerConfigStep.java
index bfc0ad8a5..037688151 100644
--- a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerConfigStep.java
+++ b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/config/FreeMarkerConfigStep.java
@@ -153,6 +153,7 @@ public int process(DocProcessContext context, DocProcessData data) throws Except
map.put(CleanTextFun.DEFAULT_NAME, new CleanTextFun());
map.put(FormatLocalDateTimeFun.DEFAULT_NAME, new FormatLocalDateTimeFun());
map.put(Base64ToStringFun.DEFAULT_NAME, new Base64ToStringFun());
+ map.put(StringToBase64Fun.DEFAULT_NAME, new StringToBase64Fun());
}
return res;
}
diff --git a/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/fun/StringToBase64Fun.java b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/fun/StringToBase64Fun.java
new file mode 100644
index 000000000..da85226d8
--- /dev/null
+++ b/fj-doc-freemarker/src/main/java/org/fugerit/java/doc/freemarker/fun/StringToBase64Fun.java
@@ -0,0 +1,23 @@
+package org.fugerit.java.doc.freemarker.fun;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateMethodModelEx;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateScalarModel;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.List;
+
+public class StringToBase64Fun implements TemplateMethodModelEx {
+
+ public static final String DEFAULT_NAME = "stringToBase64";
+
+ @Override
+ public Object exec(@SuppressWarnings("rawtypes") List arguments) throws TemplateModelException {
+ FMFunHelper.checkParameterNumber( arguments, 1 );
+ String content = ((TemplateScalarModel)arguments.get( 0 )).getAsString();
+ return new SimpleScalar( Base64.getEncoder().encodeToString( content.getBytes( StandardCharsets.UTF_8 ) ) );
+ }
+
+}
diff --git a/fj-doc-freemarker/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-freemarker/reflect-config.json b/fj-doc-freemarker/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-freemarker/reflect-config.json
index e58590f4c..2fb1d88e7 100644
--- a/fj-doc-freemarker/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-freemarker/reflect-config.json
+++ b/fj-doc-freemarker/src/main/resources/META-INF/native-image/org.fugerit.java/fj-doc-freemarker/reflect-config.json
@@ -2029,6 +2029,42 @@
"name" : "wait",
"parameterTypes" : [ "long", "int" ]
} ]
+}, {
+ "name" : "org.fugerit.java.doc.freemarker.fun.StringToBase64Fun",
+ "methods" : [ {
+ "name" : "",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "equals",
+ "parameterTypes" : [ "java.lang.Object" ]
+ }, {
+ "name" : "exec",
+ "parameterTypes" : [ "java.util.List" ]
+ }, {
+ "name" : "getClass",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "hashCode",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "notify",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "notifyAll",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "toString",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "wait",
+ "parameterTypes" : [ ]
+ }, {
+ "name" : "wait",
+ "parameterTypes" : [ "long" ]
+ }, {
+ "name" : "wait",
+ "parameterTypes" : [ "long", "int" ]
+ } ]
}, {
"name" : "org.fugerit.java.doc.freemarker.fun.TextWrapFun",
"methods" : [ {
diff --git a/fj-doc-freemarker/src/main/resources/fj_doc_freemarker_config/template/macro/html_element.ftl b/fj-doc-freemarker/src/main/resources/fj_doc_freemarker_config/template/macro/html_element.ftl
index 49eb49d82..f7f39cc04 100644
--- a/fj-doc-freemarker/src/main/resources/fj_doc_freemarker_config/template/macro/html_element.ftl
+++ b/fj-doc-freemarker/src/main/resources/fj_doc_freemarker_config/template/macro/html_element.ftl
@@ -65,7 +65,7 @@
<#assign imageAlign="style='display: block; margin-left: auto; margin-right: auto;'"/>
#if>
#if>
-
${imageAlign!''} <#if (docImage.alt)??> alt="${docImage.alt}" #if> ${imageScaling} src="data:image/png;base64, ${docImage.resolvedBase64}" />
+
${imageAlign!''} <#if (docImage.alt)??> alt="${docImage.alt}" #if> ${imageScaling} src="data:image/png;base64, <#if docImage.content?has_content>${docImage.content}<#else>${docImage.resolvedBase64}#if>" />
#if>
#macro>
diff --git a/fj-doc-freemarker/src/test/resources/fj_doc_test/freemarker-doc-process_alt.xml b/fj-doc-freemarker/src/test/resources/fj_doc_test/freemarker-doc-process_alt.xml
index 91c4f9eca..a5066e3c8 100644
--- a/fj-doc-freemarker/src/test/resources/fj_doc_test/freemarker-doc-process_alt.xml
+++ b/fj-doc-freemarker/src/test/resources/fj_doc_test/freemarker-doc-process_alt.xml
@@ -26,6 +26,7 @@
+
diff --git a/fj-doc-freemarker/src/test/resources/fj_doc_test/template/test_01.ftl b/fj-doc-freemarker/src/test/resources/fj_doc_test/template/test_01.ftl
index 0f89f4be3..b290cd597 100644
--- a/fj-doc-freemarker/src/test/resources/fj_doc_test/template/test_01.ftl
+++ b/fj-doc-freemarker/src/test/resources/fj_doc_test/template/test_01.ftl
@@ -63,6 +63,8 @@
base64ToString ${base64ToString('VEVTVA==')}
+ stringToBase64 ${stringToBase64('TEST')}
+
italic ${messageFormat()}
diff --git a/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc b/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc
index 4d78d42f9..d0d44c77c 100644
--- a/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc
+++ b/fj-doc-guide/src/main/docs/asciidoc/chapters/04_1_doc_freemarker_config.adoc
@@ -209,6 +209,16 @@ NOTE: When using *skipfm* no FreeMarker template syntax should be used in the te
| formats a LocalDate, LocalTime or LocalDateTime
| (1) - the date/time to format, (2) - the format pattern
+| base64ToString
+| org.fugerit.java.doc.freemarker.fun.Base64ToStringFun
+| converts a base64 to string
+| (1) - base64 to convert to string
+
+| stringToBase64
+| org.fugerit.java.doc.freemarker.fun.StringToBase64Fun
+| converts a string to base64
+| (1) - the string to convert
+
|========================================================================================================================================
NOTE: These functions can all be loaded at once with the config step attribute _load-bundled-functions="true"_.
\ No newline at end of file
diff --git a/fj-doc-mod-fop/src/main/java/org/fugerit/java/doc/mod/fop/PdfFopTypeHandler.java b/fj-doc-mod-fop/src/main/java/org/fugerit/java/doc/mod/fop/PdfFopTypeHandler.java
index 0b6b85456..6ed0530b6 100644
--- a/fj-doc-mod-fop/src/main/java/org/fugerit/java/doc/mod/fop/PdfFopTypeHandler.java
+++ b/fj-doc-mod-fop/src/main/java/org/fugerit/java/doc/mod/fop/PdfFopTypeHandler.java
@@ -2,6 +2,7 @@
import java.io.*;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@@ -46,6 +47,8 @@ public class PdfFopTypeHandler extends FreeMarkerFopTypeHandler {
public static final DocTypeHandler HANDLER = new PdfFopTypeHandler();
+ public static final DocTypeHandler HANDLER_UTF8 = new PdfFopTypeHandler( StandardCharsets.UTF_8 );
+
public static final String ATT_FOP_CONFIG_MODE = "fop-config-mode";
public static final String ATT_FOP_CONFIG_MODE_DEFAULT = "default";
public static final String ATT_FOP_CONFIG_MODE_CLASS_LOADER = "classloader";
diff --git a/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/fm-fop-process-config.xml b/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/fm-fop-process-config.xml
index e5084e926..45847ae0d 100644
--- a/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/fm-fop-process-config.xml
+++ b/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/fm-fop-process-config.xml
@@ -26,6 +26,7 @@
+
diff --git a/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/template/macro/doc_element.ftl b/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/template/macro/doc_element.ftl
index 5fe96a1d8..4f3c9a4f8 100644
--- a/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/template/macro/doc_element.ftl
+++ b/fj-doc-mod-fop/src/main/resources/fj_doc_mod_fop_config/template/macro/doc_element.ftl
@@ -56,7 +56,7 @@
<#macro handleImage docImage>
>
<#if docImage.svg>
- fox:alt-text="${docImage.alt}" #if> xmlns:svg="http://www.w3.org/2000/svg">${base64ToString(docImage.resolvedBase64)}
+ fox:alt-text="${docImage.alt}" #if> xmlns:svg="http://www.w3.org/2000/svg"><#if docImage.content?has_content>${docImage.content}<#else>${base64ToString(docImage.resolvedBase64)}#if>
<#else>
<#if (docImage.scaling)??>
<#assign imageScaling="height='${docImage.scaling}%' content-height='${docImage.scaling}%' content-width='scale-to-fit' scaling='uniform' width='${docImage.scaling}%'"/>
diff --git a/fj-doc-mod-fop/src/test/java/test/org/fugerit/java/doc/mod/fop/TestIssue580SpecialCharacters.java b/fj-doc-mod-fop/src/test/java/test/org/fugerit/java/doc/mod/fop/TestIssue580SpecialCharacters.java
new file mode 100644
index 000000000..277641264
--- /dev/null
+++ b/fj-doc-mod-fop/src/test/java/test/org/fugerit/java/doc/mod/fop/TestIssue580SpecialCharacters.java
@@ -0,0 +1,62 @@
+package test.org.fugerit.java.doc.mod.fop;
+
+import lombok.extern.slf4j.Slf4j;
+import org.fugerit.java.core.lang.helpers.ClassHelper;
+import org.fugerit.java.core.xml.dom.DOMIO;
+import org.fugerit.java.doc.base.config.DocInput;
+import org.fugerit.java.doc.base.config.DocOutput;
+import org.fugerit.java.doc.base.config.DocTypeHandler;
+import org.fugerit.java.doc.base.config.DocTypeHandlerDefault;
+import org.fugerit.java.doc.mod.fop.PdfFopTypeHandler;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Element;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+class TestIssue580SpecialCharacters {
+
+ private static final String PATH_XML_SAMPLE = "issue/gh580/sample-gh580.xml";
+
+ private static final String PATH_XML_SAMPLE_ALT_FONT = "issue/gh580/sample-gh580-alt-font.xml";
+
+ private File testWorker( DocTypeHandler handler, String xmlPath, String outputPath ) throws Exception {
+ log.info( "xml path : {}, handler: {}, type: {}", xmlPath, handler.getClass().getName(), handler.getType() );
+ File outputFile = new File( outputPath );
+ log.info( "output file: {}, delete : {}", outputFile.getAbsolutePath(), outputFile.delete() );
+ try (Reader reader = new InputStreamReader( ClassHelper.loadFromDefaultClassLoader(xmlPath) );
+ OutputStream os = new FileOutputStream( outputFile ) ) {
+ handler.handle( DocInput.newInput( handler.getType(), reader ), DocOutput.newOutput( os ) );
+ }
+ return outputFile;
+ }
+
+ /*
+ * working example using SVG :
+ *
+ */
+ @Test
+ void testGeneratedPdf() throws Exception {
+ DocTypeHandler handler = PdfFopTypeHandler.HANDLER_UTF8;
+ File outputFile = this.testWorker( handler, PATH_XML_SAMPLE, "target/issue-gh580.pdf" );
+ Assertions.assertTrue( outputFile.exists() ) ;
+ }
+
+ /*
+ * working example using DejaVu Font https://dejavu-fonts.github.io/
+ */
+ @Test
+ void testGeneratedPdfWithAlternateFont() throws Exception {
+ DocTypeHandlerDefault handler = new PdfFopTypeHandler(StandardCharsets.UTF_8);
+ String xmlConfig = "\n";
+ Element element = DOMIO.loadDOMDoc( xmlConfig ).getDocumentElement();
+ handler.configure( element );
+ File outputFile = this.testWorker( handler, PATH_XML_SAMPLE_ALT_FONT, "target/issue-gh580-alt-font.pdf" );
+ Assertions.assertTrue( outputFile.exists() ) ;
+ }
+
+}
diff --git a/fj-doc-mod-fop/src/test/resources/issue/gh580/DejaVuSans.ttf b/fj-doc-mod-fop/src/test/resources/issue/gh580/DejaVuSans.ttf
new file mode 100644
index 000000000..e5f7eecce
Binary files /dev/null and b/fj-doc-mod-fop/src/test/resources/issue/gh580/DejaVuSans.ttf differ
diff --git a/fj-doc-mod-fop/src/test/resources/issue/gh580/fop-config-issue-580.xml b/fj-doc-mod-fop/src/test/resources/issue/gh580/fop-config-issue-580.xml
new file mode 100644
index 000000000..34f7a4ff3
--- /dev/null
+++ b/fj-doc-mod-fop/src/test/resources/issue/gh580/fop-config-issue-580.xml
@@ -0,0 +1,35 @@
+
+
+
+ true
+
+
+ true
+
+
+ .
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 72
+
+ 72
+
+
+
+
+
\ No newline at end of file
diff --git a/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580-alt-font.xml b/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580-alt-font.xml
new file mode 100644
index 000000000..2b9804259
--- /dev/null
+++ b/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580-alt-font.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ 10;10;10;30
+ Basic example alt font
+ fj doc venus sample source xml
+ fugerit79
+ it
+ true
+ DejaVuSans
+
+
+ Sample special characters reproducer ■ □ ■ □ with font DejaVuSans
+
+
+
\ No newline at end of file
diff --git a/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580.xml b/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580.xml
new file mode 100644
index 000000000..0e9503baa
--- /dev/null
+++ b/fj-doc-mod-fop/src/test/resources/issue/gh580/sample-gh580.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ 10;10;10;30
+ Basic example
+ fj doc venus sample source xml
+ fugerit79
+ it
+ true
+
+
+ Sample special characters reproducer ■ □ ■ □
+ Working POC with SVG :
+ ]]>
+
+
+
\ No newline at end of file