Allow quoting hypertext attribute values (#14550)

This commit is contained in:
rubenwardy 2024-05-05 13:27:17 +01:00 committed by GitHub
parent d748c8c653
commit 3017b0213b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 20 deletions

@ -3535,10 +3535,12 @@ Markup language used in `hypertext[]` elements uses tags that look like HTML tag
The markup language is currently unstable and subject to change. Use with caution. The markup language is currently unstable and subject to change. Use with caution.
Some tags can enclose text, they open with `<tagname>` and close with `</tagname>`. Some tags can enclose text, they open with `<tagname>` and close with `</tagname>`.
Tags can have attributes, in that case, attributes are in the opening tag in Tags can have attributes, in that case, attributes are in the opening tag in
form of a key/value separated with equal signs. Attribute values should not be quoted. form of a key/value separated with equal signs.
Attribute values should be quoted using either " or '.
If you want to insert a literal greater-than sign or a backslash into the text, If you want to insert a literal greater-than, less-than, or a backslash into the text,
you must escape it by preceding it with a backslash. you must escape it by preceding it with a backslash. In a quoted attribute value, you
can insert a literal quote mark by preceding it with a backslash.
These are the technically basic tags but see below for usual tags. Base tags are: These are the technically basic tags but see below for usual tags. Base tags are:

@ -69,9 +69,9 @@ local hypertext_basic = [[A hypertext element
This is a normal text. This is a normal text.
<bigger><mono>style</mono> test</bigger> <bigger><mono>style</mono> test</bigger>
<style color=#FFFF00>Yellow text.</style> <style color=#FF0000>Red text.</style> <style color="#FFFF00">Yellow text.</style> <style color='#FF0000'>Red text.</style>
<style size=24>Size 24.</style> <style size=16>Size 16</style>. <style size=12>Size 12.</style> <style size="24">Size 24.</style> <style size=16>Size 16</style>. <style size=12>Size 12.</style>
<style font=normal>Normal font.</style> <style font=mono>Mono font.</style> <style font="normal">Normal font.</style> <style font=mono>Mono font.</style>
<bigger>Tag test</bigger> <bigger>Tag test</bigger>
<normal>normal</normal> <normal>normal</normal>
@ -88,20 +88,20 @@ This is a normal text.
<bigger>Custom tag test</bigger> <bigger>Custom tag test</bigger>
<tag name=t_green color=green> <tag name=t_green color=green>
<tag name=t_hover hovercolor=yellow> <tag name="t_hover" hovercolor=yellow>
<tag name=t_size size=24> <tag name="t_size" size=24>
<tag name=t_mono font=mono> <tag name="t_mono" font=mono>
<tag name=t_multi color=green font=mono size=24> <tag name="t_multi" color=green font=mono size=24>
<t_green>color=green</t_green> <t_green>color=green</t_green>
Action: <action name=color><t_green>color=green</t_green></action> Action: <action name="color"><t_green>color=green</t_green></action>
Action: <action name=hovercolor><t_hover>hovercolor=yellow</t_hover></action> Action: <action name="hovercolor"><t_hover>hovercolor=yellow</t_hover></action>
Action URL: <action name=open url=https://example.com/?a=b#c>open URL</action> Action URL: <action name="open" url="https://example.com/?a=b#c">open URL</action>
<t_size>size=24</t_size> <t_size>size=24</t_size>
<t_mono>font=mono</t_mono> <t_mono>font=mono</t_mono>
<t_multi>color=green font=mono size=24</t_multi> <t_multi>color=green font=mono size=24</t_multi>
<bigger><mono>action</mono> test</bigger> <bigger><mono>action</mono> test</bigger>
<action name=action_test>action</action> <action name="action_test">action</action>
<bigger><mono>img</mono> test</bigger> <bigger><mono>img</mono> test</bigger>
Normal: Normal:

@ -421,14 +421,16 @@ u32 ParsedText::parseTag(const wchar_t *text, u32 cursor)
AttrsList attrs; AttrsList attrs;
while (c != L'>') { while (c != L'>') {
std::string attr_name = ""; std::string attr_name = "";
core::stringw attr_val = L""; std::wstring attr_val = L"";
// Consume whitespace
while (c == ' ') { while (c == ' ') {
c = text[++cursor]; c = text[++cursor];
if (c == L'\0' || c == L'=') if (c == L'\0' || c == L'=')
return 0; return 0;
} }
// Read attribute name
while (c != L' ' && c != L'=') { while (c != L' ' && c != L'=') {
attr_name += (char)c; attr_name += (char)c;
c = text[++cursor]; c = text[++cursor];
@ -436,28 +438,51 @@ u32 ParsedText::parseTag(const wchar_t *text, u32 cursor)
return 0; return 0;
} }
// Consume whitespace
while (c == L' ') { while (c == L' ') {
c = text[++cursor]; c = text[++cursor];
if (c == L'\0' || c == L'>') if (c == L'\0' || c == L'>')
return 0; return 0;
} }
// Skip equals
if (c != L'=') if (c != L'=')
return 0; return 0;
c = text[++cursor]; c = text[++cursor];
if (c == L'\0') if (c == L'\0')
return 0; return 0;
while (c != L'>' && c != L' ') { // Read optional quote
attr_val += c; wchar_t quote_used = 0;
if (c == L'"' || c == L'\'') {
quote_used = c;
c = text[++cursor]; c = text[++cursor];
if (c == L'\0') if (c == L'\0')
return 0; return 0;
} }
attrs[attr_name] = stringw_to_utf8(attr_val); // Read attribute value
bool escape = false;
while (escape || (quote_used && c != quote_used) || (!quote_used && c != L'>' && c != L' ')) {
if (quote_used && !escape && c == L'\\') {
escape = true;
} else {
escape = false;
attr_val += c;
}
c = text[++cursor];
if (c == L'\0')
return 0;
}
// Remove quote
if (quote_used) {
if (c != quote_used)
return 0;
c = text[++cursor];
}
attrs[attr_name] = wide_to_utf8(attr_val);
} }
++cursor; // Last ">" ++cursor; // Last ">"