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.
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
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,
you must escape it by preceding it with a backslash.
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. 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:

@ -69,9 +69,9 @@ local hypertext_basic = [[A hypertext element
This is a normal text.
<bigger><mono>style</mono> test</bigger>
<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 font=normal>Normal font.</style> <style font=mono>Mono font.</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 font="normal">Normal font.</style> <style font=mono>Mono font.</style>
<bigger>Tag test</bigger>
<normal>normal</normal>
@ -88,20 +88,20 @@ This is a normal text.
<bigger>Custom tag test</bigger>
<tag name=t_green color=green>
<tag name=t_hover hovercolor=yellow>
<tag name=t_size size=24>
<tag name=t_mono font=mono>
<tag name=t_multi color=green font=mono size=24>
<tag name="t_hover" hovercolor=yellow>
<tag name="t_size" size=24>
<tag name="t_mono" font=mono>
<tag name="t_multi" color=green font=mono size=24>
<t_green>color=green</t_green>
Action: <action name=color><t_green>color=green</t_green></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: <action name="color"><t_green>color=green</t_green></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>
<t_size>size=24</t_size>
<t_mono>font=mono</t_mono>
<t_multi>color=green font=mono size=24</t_multi>
<bigger><mono>action</mono> test</bigger>
<action name=action_test>action</action>
<action name="action_test">action</action>
<bigger><mono>img</mono> test</bigger>
Normal:

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