Skip to content
This repository was archived by the owner on Dec 4, 2025. It is now read-only.

Commit 5c36b5d

Browse files
kienmatulinwumingshi
authored andcommitted
feat: refactor function package: HtmlEscape and WordXmlEscape
1 parent 9d708ff commit 5c36b5d

File tree

4 files changed

+174
-17
lines changed

4 files changed

+174
-17
lines changed

src/main/java/com/ly/doc/function/HtmlEscape.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,47 @@
2525
import org.beetl.core.Context;
2626
import org.beetl.core.Function;
2727

28+
import java.util.HashMap;
29+
import java.util.Map;
30+
2831
/**
29-
* beetl template function
32+
* Function to escape HTML content in Beetl templates.
33+
* <p>
34+
* This class provides a method to replace specific HTML characters with their
35+
* corresponding escape sequences and clean up comments.
36+
* <p>
37+
* For example, it replaces:
38+
* <p>
39+
* - <code>"</code> with <code>&amp;quot;</code>
3040
*
31-
* @author yu 2021/6/26.
41+
* @author yu
42+
* @since 2021/6/26
3243
*/
3344
public class HtmlEscape implements Function {
3445

46+
/**
47+
* Map to hold HTML escape sequences.
48+
*/
49+
private static final Map<String, String> HTML_ESCAPE_MAP;
50+
51+
static {
52+
HTML_ESCAPE_MAP = new HashMap<>();
53+
HTML_ESCAPE_MAP.put("<p>", "");
54+
HTML_ESCAPE_MAP.put("</p>", " ");
55+
}
56+
3557
@Override
36-
public String call(Object[] paras, Context ctx) {
37-
String str = String.valueOf(paras[0]).replaceAll("&", "&amp;");
38-
str = str.replaceAll("\"", "&quot;");
39-
str = str.replaceAll("<p>", "").replaceAll("</p>", " ");
40-
return DocUtil.replaceNewLineToHtmlBr(DocUtil.getEscapeAndCleanComment(str));
58+
public String call(Object[] params, Context ctx) {
59+
if (params == null || params.length == 0 || params[0] == null) {
60+
return "";
61+
}
62+
String html = String.valueOf(params[0]);
63+
for (Map.Entry<String, String> entry : HTML_ESCAPE_MAP.entrySet()) {
64+
html = html.replace(entry.getKey(), entry.getValue());
65+
}
66+
67+
html = DocUtil.getEscapeAndCleanComment(html);
68+
return DocUtil.replaceNewLineToHtmlBr(html);
4169
}
4270

4371
}

src/main/java/com/ly/doc/function/WordXmlEscape.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,50 @@
2020
*/
2121
package com.ly.doc.function;
2222

23+
import java.util.LinkedHashMap;
24+
import java.util.Map;
25+
2326
import com.ly.doc.utils.DocUtil;
2427
import org.beetl.core.Context;
2528
import org.beetl.core.Function;
2629

2730
/**
28-
* beetl template function
31+
* Function to escape XML content in Beetl templates.
32+
* <p>
33+
* For example, it replaces: - <code>" "</code> with <code> </code>
2934
*
3035
* @author yu 2021/6/26.
3136
*/
3237
public class WordXmlEscape implements Function {
3338

39+
/*
40+
* Represents a non-breaking space character (U+00A0) commonly used in Word documents.
41+
* In HTML, this character is typically represented as "&nbsp;".
42+
*/
43+
private static final String UNICODE_NON_BREAK_SPACE = "\u00A0";
44+
45+
private static final Map<String, String> XML_ESCAPE_MAP;
46+
47+
static {
48+
XML_ESCAPE_MAP = new LinkedHashMap<>();
49+
XML_ESCAPE_MAP.put(" ", UNICODE_NON_BREAK_SPACE);
50+
XML_ESCAPE_MAP.put("&nbsp;&nbsp;", UNICODE_NON_BREAK_SPACE);
51+
XML_ESCAPE_MAP.put("&nbsp;", "");
52+
XML_ESCAPE_MAP.put("<br/>", "");
53+
}
54+
3455
@Override
35-
public String call(Object[] paras, Context ctx) {
36-
String str = String.valueOf(paras[0])
37-
.replaceAll(" ", " ")
38-
.replaceAll("&nbsp;&nbsp;", " ")
39-
.replaceAll("&nbsp;", "")
40-
.replaceAll("<br/>", "")
41-
.replaceAll("&", "&amp;")
42-
.replaceAll("<", "&lt;");
43-
return DocUtil.getEscapeAndCleanComment(str);
56+
public String call(Object[] params, Context ctx) {
57+
if (params == null || params.length == 0 || params[0] == null) {
58+
return "";
59+
}
60+
61+
String xml = String.valueOf(params[0]);
62+
for (Map.Entry<String, String> entry : XML_ESCAPE_MAP.entrySet()) {
63+
xml = xml.replaceAll(entry.getKey(), entry.getValue());
64+
}
65+
66+
return DocUtil.getEscapeAndCleanComment(xml);
4467
}
4568

4669
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.ly.doc.function;
2+
3+
import org.beetl.core.Context;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.Arguments;
6+
import org.junit.jupiter.params.provider.MethodSource;
7+
import org.junit.jupiter.params.provider.NullAndEmptySource;
8+
9+
import java.util.stream.Stream;
10+
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
13+
class HtmlEscapeTest {
14+
15+
/*
16+
* Since context is not used in the function, we can set it to null.
17+
*/
18+
private static final Context context = null;
19+
20+
@ParameterizedTest
21+
@MethodSource("provideNormalTestCases")
22+
void testHtmlEscape(String input, String expected) {
23+
HtmlEscape htmlEscape = new HtmlEscape();
24+
25+
String result = htmlEscape.call(new Object[] { input }, context);
26+
27+
assertEquals(expected, result);
28+
}
29+
30+
@ParameterizedTest
31+
@NullAndEmptySource
32+
void testHtmlEscapeNullAndEmptyString(Object[] input) {
33+
HtmlEscape htmlEscape = new HtmlEscape();
34+
35+
String result = htmlEscape.call(input, context);
36+
37+
assertEquals("", result);
38+
}
39+
40+
/**
41+
* Provides test cases for normal inputs.
42+
* @return a stream of arguments for testing
43+
*/
44+
static Stream<Arguments> provideNormalTestCases() {
45+
return Stream.of(Arguments.of("&", "&amp;"), Arguments.of("\"", "&quot;"), Arguments.of("<p>", ""),
46+
Arguments.of("<p>ab</p>abc", "ab abc"), Arguments.of("</p>", ""),
47+
Arguments.of("<p>Hello & \"World\"</p>", "Hello &amp; &quot;World&quot; "), Arguments.of("", ""),
48+
Arguments.of(null, ""));
49+
}
50+
51+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.ly.doc.function;
2+
3+
import org.beetl.core.Context;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.Arguments;
6+
import org.junit.jupiter.params.provider.MethodSource;
7+
import org.junit.jupiter.params.provider.NullAndEmptySource;
8+
9+
import java.util.stream.Stream;
10+
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
13+
class WordXmlEscapeTest {
14+
15+
private static final String UNICODE_NON_BREAK_SPACE = "\u00A0";
16+
17+
private static Context context;
18+
19+
@ParameterizedTest
20+
@MethodSource("provideNormalTestCases")
21+
void testWordXmlEscape(String input, String expected) {
22+
WordXmlEscape wordXmlEscape = new WordXmlEscape();
23+
24+
String result = wordXmlEscape.call(new Object[] { input }, context);
25+
26+
assertEquals(expected, result);
27+
}
28+
29+
@ParameterizedTest
30+
@NullAndEmptySource
31+
void testWordXmlEscapeNullAndEmptyString(Object[] input) {
32+
WordXmlEscape wordXmlEscape = new WordXmlEscape();
33+
34+
String result = wordXmlEscape.call(input, context);
35+
36+
assertEquals("", result);
37+
}
38+
39+
/**
40+
* Provides test cases for normal inputs.
41+
* @return a stream of arguments for testing
42+
*/
43+
static Stream<Arguments> provideNormalTestCases() {
44+
return Stream.of(Arguments.of(" ", UNICODE_NON_BREAK_SPACE),
45+
Arguments.of("&nbsp;&nbsp;", UNICODE_NON_BREAK_SPACE), Arguments.of("&nbsp;", ""),
46+
// Combination of doubled non-breaking spaces and empty spaces
47+
Arguments.of("&nbsp;&nbsp; abc&nbsp;",
48+
String.format("%s%sabc", UNICODE_NON_BREAK_SPACE, UNICODE_NON_BREAK_SPACE)),
49+
Arguments.of("<br/>", ""), Arguments.of("&", "&amp;"), Arguments.of("<", "&lt;"),
50+
Arguments.of("Hello & <br/>",
51+
String.format("Hello%s&amp;%s", UNICODE_NON_BREAK_SPACE, UNICODE_NON_BREAK_SPACE)),
52+
Arguments.of("", ""), Arguments.of(null, ""));
53+
}
54+
55+
}

0 commit comments

Comments
 (0)