Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qute - add unparsed character data #10038

Merged
merged 1 commit into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ NOTE: In Quarkus, the caching is done automatically.
The dynamic parts of a template include:

* *Comment*
** `{! This is a comment !}`,
** Starts with `{!` and ends with `!}`: `{! This is a comment !}`,
** Could be multi-line,
** May contain expressions and sections: `{! {#if true} !}`.
* *Expression*
Expand All @@ -93,6 +93,10 @@ The dynamic parts of a template include:
** The name in the closing tag is optional: `{#if active}ACTIVE!{/}`,
** Can be empty: `{#myTag image=true /}`,
** May declare nested section blocks: `{#if item.valid} Valid. {#else} Invalid. {/if}` and decide which block to render.
* *Unparsed Character Data*
** Starts with `{[` and ends with `]}`: `{[ <script>if(true){alert('Qute is cute!')};</script> ]}`,
** Could be multi-line,
** Used to mark the content that should be rendered but not parsed.

=== Identifiers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Parser implements Function<String, Expression> {
private static final char START_DELIMITER = '{';
private static final char END_DELIMITER = '}';
private static final char COMMENT_DELIMITER = '!';
private static final char CDATA_START_DELIMITER = '[';
private static final char CDATA_END_DELIMITER = ']';
private static final char UNDERSCORE = '_';
private static final char ESCAPE_CHAR = '\\';

Expand Down Expand Up @@ -151,6 +153,9 @@ private void processCharacter(char character) {
case COMMENT:
comment(character);
break;
case CDATA:
cdata(character);
break;
case TAG_CANDIDATE:
tagCandidate(character);
break;
Expand Down Expand Up @@ -193,6 +198,17 @@ private void comment(char character) {
}
}

private void cdata(char character) {
if (character == END_DELIMITER && buffer.length() > 0 && buffer.charAt(buffer.length() - 1) == CDATA_END_DELIMITER) {
// End of cdata
state = State.TEXT;
buffer.deleteCharAt(buffer.length() - 1);
flushText();
} else {
buffer.append(character);
}
}

private void tag(char character) {
if (character == END_DELIMITER) {
flushTag();
Expand All @@ -205,8 +221,15 @@ private void tagCandidate(char character) {
if (isValidIdentifierStart(character)) {
// Real tag start, flush text if any
flushText();
state = character == COMMENT_DELIMITER ? State.COMMENT : State.TAG_INSIDE;
buffer.append(character);
if (character == COMMENT_DELIMITER) {
buffer.append(character);
state = State.COMMENT;
} else if (character == CDATA_START_DELIMITER) {
state = State.CDATA;
} else {
buffer.append(character);
state = State.TAG_INSIDE;
}
} else {
// Ignore expressions/tags starting with an invalid identifier
buffer.append(START_DELIMITER).append(character);
Expand All @@ -219,8 +242,9 @@ private void tagCandidate(char character) {
}

private boolean isValidIdentifierStart(char character) {
// A valid identifier must start with a digit, alphabet, underscore, comment delimiter or a tag command (e.g. # for sections)
return Tag.isCommand(character) || character == COMMENT_DELIMITER || character == UNDERSCORE
// A valid identifier must start with a digit, alphabet, underscore, comment delimiter, cdata start delimiter or a tag command (e.g. # for sections)
return Tag.isCommand(character) || character == COMMENT_DELIMITER || character == CDATA_START_DELIMITER
|| character == UNDERSCORE
|| Character.isDigit(character)
|| Character.isAlphabetic(character);
}
Expand Down Expand Up @@ -570,6 +594,7 @@ enum State {
TAG_CANDIDATE,
COMMENT,
ESCAPE,
CDATA,

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ public void testWhitespace() {
assertEquals("Hello world", engine.parse("Hello {name ?: 'world' }").render());
}

@Test
public void testCdata() {
Engine engine = Engine.builder().addDefaults().build();
String jsSnippet = "<script>const foo = function(){alert('bar');};</script>";
try {
engine.parse("Hello {name} " + jsSnippet);
fail();
} catch (Exception expected) {
}
assertEquals("Hello world <script>const foo = function(){alert('bar');};</script>", engine.parse("Hello {name} {["
+ jsSnippet
+ "]}").data("name", "world").render());
assertEquals("Hello world <strong>", engine.parse("Hello {name} {[<strong>]}").data("name", "world").render());
}

private void assertParserError(String template, String message, int line) {
Engine engine = Engine.builder().addDefaultSectionHelpers().build();
try {
Expand Down