-
-
Notifications
You must be signed in to change notification settings - Fork 7
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
Ampersand (&) results in incorrect rendering of HTML #18
Comments
@dangrima90 i dont understand your issue. What you describe seems ok to me. |
@farfromrefug maybe I did not explain myself properly. The issue is that when having an & in the text HTML is not rendered as expected. Code: <HtmlLabel :html="`<h1>T&Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<h1>T&Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<h1>T and Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<span>T&Cs</span>`" linkColor="blue" />
<HtmlLabel :html="`<span>T&Cs</span>`" linkColor="blue" />
<HtmlLabel :html="`<span>T and Cs</span>`" linkColor="blue" />
<HtmlLabel
:html="`<a href='https://www.google.com'>T&Cs</a>`"
linkColor="blue"
/>
<HtmlLabel
:html="`<a href='https://www.google.com'>T&Cs</a>`"
linkColor="blue"
/>
<HtmlLabel
:html="`<a href='https://www.google.com'>T and Cs</a>`"
linkColor="blue"
/> Screenshot: The text you see highlighted with the red box appear as raw HTML rather than rendered as HTML. |
@dangrima90 i get it now thanks! |
Hi @farfromrefug any updates on this please? |
@dangrima90 no sorry it is not on my priority list right now as it can for now be fixed with a text replace. |
@farfromrefug I've tested this out with the repo's demo and I can verify the following:
To test I've extracted all the characters listed here (https://www.freeformatter.com/html-entities.html) and tested them out in the Code Snippet<script lang="ts"> import * as frameModule from '@nativescript/core/ui/frame'; import Vue from 'vue'; export const title = 'ListView sample'; function getRandomColor() { var letters = '0123456789ABCDEF'; var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } export default Vue.extend({ data() { return { title: title, item: null, items: [ { color: getRandomColor(), text: '!' }, { color: getRandomColor(), text: '#' }, { color: getRandomColor(), text: '$' }, { color: getRandomColor(), text: '%' }, { color: getRandomColor(), text: '&' }, { color: getRandomColor(), text: "'" }, { color: getRandomColor(), text: '(' }, { color: getRandomColor(), text: ')' }, { color: getRandomColor(), text: '*' }, { color: getRandomColor(), text: '+' }, { color: getRandomColor(), text: ',' }, { color: getRandomColor(), text: '-' }, { color: getRandomColor(), text: '.' }, { color: getRandomColor(), text: '/' }, { color: getRandomColor(), text: '0' }, { color: getRandomColor(), text: '1' }, { color: getRandomColor(), text: '2' }, { color: getRandomColor(), text: '3' }, { color: getRandomColor(), text: '4' }, { color: getRandomColor(), text: '5' }, { color: getRandomColor(), text: '6' }, { color: getRandomColor(), text: '7' }, { color: getRandomColor(), text: '8' }, { color: getRandomColor(), text: '9' }, { color: getRandomColor(), text: ':' }, { color: getRandomColor(), text: ';' }, { color: getRandomColor(), text: '<' }, { color: getRandomColor(), text: '=' }, { color: getRandomColor(), text: '>' }, { color: getRandomColor(), text: '?' }, { color: getRandomColor(), text: '@' }, { color: getRandomColor(), text: 'A' }, { color: getRandomColor(), text: 'B' }, { color: getRandomColor(), text: 'C' }, { color: getRandomColor(), text: 'D' }, { color: getRandomColor(), text: 'E' }, { color: getRandomColor(), text: 'F' }, { color: getRandomColor(), text: 'G' }, { color: getRandomColor(), text: 'H' }, { color: getRandomColor(), text: 'I' }, { color: getRandomColor(), text: 'J' }, { color: getRandomColor(), text: 'K' }, { color: getRandomColor(), text: 'L' }, { color: getRandomColor(), text: 'M' }, { color: getRandomColor(), text: 'N' }, { color: getRandomColor(), text: 'O' }, { color: getRandomColor(), text: 'P' }, { color: getRandomColor(), text: 'Q' }, { color: getRandomColor(), text: 'R' }, { color: getRandomColor(), text: 'S' }, { color: getRandomColor(), text: 'T' }, { color: getRandomColor(), text: 'U' }, { color: getRandomColor(), text: 'V' }, { color: getRandomColor(), text: 'W' }, { color: getRandomColor(), text: 'X' }, { color: getRandomColor(), text: 'Y' }, { color: getRandomColor(), text: 'Z' }, { color: getRandomColor(), text: '[' }, { color: getRandomColor(), text: '\\\\' }, { color: getRandomColor(), text: ']' }, { color: getRandomColor(), text: '^' }, { color: getRandomColor(), text: '_' }, { color: getRandomColor(), text: '`' }, { color: getRandomColor(), text: 'a' }, { color: getRandomColor(), text: 'b' }, { color: getRandomColor(), text: 'c' }, { color: getRandomColor(), text: 'd' }, { color: getRandomColor(), text: 'e' }, { color: getRandomColor(), text: 'f' }, { color: getRandomColor(), text: 'g' }, { color: getRandomColor(), text: 'h' }, { color: getRandomColor(), text: 'i' }, { color: getRandomColor(), text: 'j' }, { color: getRandomColor(), text: 'k' }, { color: getRandomColor(), text: 'l' }, { color: getRandomColor(), text: 'm' }, { color: getRandomColor(), text: 'n' }, { color: getRandomColor(), text: 'o' }, { color: getRandomColor(), text: 'p' }, { color: getRandomColor(), text: 'q' }, { color: getRandomColor(), text: 'r' }, { color: getRandomColor(), text: 's' }, { color: getRandomColor(), text: 't' }, { color: getRandomColor(), text: 'u' }, { color: getRandomColor(), text: 'v' }, { color: getRandomColor(), text: 'w' }, { color: getRandomColor(), text: 'x' }, { color: getRandomColor(), text: 'y' }, { color: getRandomColor(), text: 'z' }, { color: getRandomColor(), text: '{' }, { color: getRandomColor(), text: '|' }, { color: getRandomColor(), text: '}' }, { color: getRandomColor(), text: '~' }, { color: getRandomColor(), text: '!' }, { color: getRandomColor(), text: '#' }, { color: getRandomColor(), text: '$' }, { color: getRandomColor(), text: '%' }, { color: getRandomColor(), text: '&' }, { color: getRandomColor(), text: "'" }, { color: getRandomColor(), text: '(' }, { color: getRandomColor(), text: ')' }, { color: getRandomColor(), text: '*' }, { color: getRandomColor(), text: '+' }, { color: getRandomColor(), text: ',' }, { color: getRandomColor(), text: '-' }, { color: getRandomColor(), text: '.' }, { color: getRandomColor(), text: '/' }, { color: getRandomColor(), text: '0' }, { color: getRandomColor(), text: '1' }, { color: getRandomColor(), text: '2' }, { color: getRandomColor(), text: '3' }, { color: getRandomColor(), text: '4' }, { color: getRandomColor(), text: '5' }, { color: getRandomColor(), text: '6' }, { color: getRandomColor(), text: '7' }, { color: getRandomColor(), text: '8' }, { color: getRandomColor(), text: '9' }, { color: getRandomColor(), text: ':' }, { color: getRandomColor(), text: ';' }, { color: getRandomColor(), text: '<' }, { color: getRandomColor(), text: '=' }, { color: getRandomColor(), text: '>' }, { color: getRandomColor(), text: '?' }, { color: getRandomColor(), text: '@' }, { color: getRandomColor(), text: 'A' }, { color: getRandomColor(), text: 'B' }, { color: getRandomColor(), text: 'C' }, { color: getRandomColor(), text: 'D' }, { color: getRandomColor(), text: 'E' }, { color: getRandomColor(), text: 'F' }, { color: getRandomColor(), text: 'G' }, { color: getRandomColor(), text: 'H' }, { color: getRandomColor(), text: 'I' }, { color: getRandomColor(), text: 'J' }, { color: getRandomColor(), text: 'K' }, { color: getRandomColor(), text: 'L' }, { color: getRandomColor(), text: 'M' }, { color: getRandomColor(), text: 'N' }, { color: getRandomColor(), text: 'O' }, { color: getRandomColor(), text: 'P' }, { color: getRandomColor(), text: 'Q' }, { color: getRandomColor(), text: 'R' }, { color: getRandomColor(), text: 'S' }, { color: getRandomColor(), text: 'T' }, { color: getRandomColor(), text: 'U' }, { color: getRandomColor(), text: 'V' }, { color: getRandomColor(), text: 'W' }, { color: getRandomColor(), text: 'X' }, { color: getRandomColor(), text: 'Y' }, { color: getRandomColor(), text: 'Z' }, { color: getRandomColor(), text: '[' }, { color: getRandomColor(), text: '\\\\' }, { color: getRandomColor(), text: ']' }, { color: getRandomColor(), text: '^' }, { color: getRandomColor(), text: '_' }, { color: getRandomColor(), text: '`' }, { color: getRandomColor(), text: 'a' }, { color: getRandomColor(), text: 'b' }, { color: getRandomColor(), text: 'c' }, { color: getRandomColor(), text: 'd' }, { color: getRandomColor(), text: 'e' }, { color: getRandomColor(), text: 'f' }, { color: getRandomColor(), text: 'g' }, { color: getRandomColor(), text: 'h' }, { color: getRandomColor(), text: 'i' }, { color: getRandomColor(), text: 'j' }, { color: getRandomColor(), text: 'k' }, { color: getRandomColor(), text: 'l' }, { color: getRandomColor(), text: 'm' }, { color: getRandomColor(), text: 'n' }, { color: getRandomColor(), text: 'o' }, { color: getRandomColor(), text: 'p' }, { color: getRandomColor(), text: 'q' }, { color: getRandomColor(), text: 'r' }, { color: getRandomColor(), text: 's' }, { color: getRandomColor(), text: 't' }, { color: getRandomColor(), text: 'u' }, { color: getRandomColor(), text: 'v' }, { color: getRandomColor(), text: 'w' }, { color: getRandomColor(), text: 'x' }, { color: getRandomColor(), text: 'y' }, { color: getRandomColor(), text: 'z' }, { color: getRandomColor(), text: '{' }, { color: getRandomColor(), text: '|' }, { color: getRandomColor(), text: '}' }, { color: getRandomColor(), text: '~' }, { color: getRandomColor(), text: '¡' }, { color: getRandomColor(), text: '¢' }, { color: getRandomColor(), text: '£' }, { color: getRandomColor(), text: '¤' }, { color: getRandomColor(), text: '¥' }, { color: getRandomColor(), text: '¦' }, { color: getRandomColor(), text: '§' }, { color: getRandomColor(), text: '¨' }, { color: getRandomColor(), text: '©' }, { color: getRandomColor(), text: 'ª' }, { color: getRandomColor(), text: '«' }, { color: getRandomColor(), text: '¬' }, { color: getRandomColor(), text: '' }, { color: getRandomColor(), text: '®' }, { color: getRandomColor(), text: '¯' }, { color: getRandomColor(), text: '°' }, { color: getRandomColor(), text: '±' }, { color: getRandomColor(), text: '²' }, { color: getRandomColor(), text: '³' }, { color: getRandomColor(), text: '´' }, { color: getRandomColor(), text: 'µ' }, { color: getRandomColor(), text: '¶' }, { color: getRandomColor(), text: '¸' }, { color: getRandomColor(), text: '¹' }, { color: getRandomColor(), text: 'º' }, { color: getRandomColor(), text: '»' }, { color: getRandomColor(), text: '¼' }, { color: getRandomColor(), text: '½' }, { color: getRandomColor(), text: '¾' }, { color: getRandomColor(), text: '¿' }, { color: getRandomColor(), text: '×' }, { color: getRandomColor(), text: '÷' }, { color: getRandomColor(), text: '∀' }, { color: getRandomColor(), text: '∂' }, { color: getRandomColor(), text: '∃' }, { color: getRandomColor(), text: '∅' }, { color: getRandomColor(), text: '∇' }, { color: getRandomColor(), text: '∈' }, { color: getRandomColor(), text: '∉' }, { color: getRandomColor(), text: '∋' }, { color: getRandomColor(), text: '∏' }, { color: getRandomColor(), text: '∑' }, { color: getRandomColor(), text: '−' }, { color: getRandomColor(), text: '∗' }, { color: getRandomColor(), text: '√' }, { color: getRandomColor(), text: '∝' }, { color: getRandomColor(), text: '∞' }, { color: getRandomColor(), text: '∠' }, { color: getRandomColor(), text: '∧' }, { color: getRandomColor(), text: '∨' }, { color: getRandomColor(), text: '∩' }, { color: getRandomColor(), text: '∪' }, { color: getRandomColor(), text: '∫' }, { color: getRandomColor(), text: '∴' }, { color: getRandomColor(), text: '∼' }, { color: getRandomColor(), text: '≅' }, { color: getRandomColor(), text: '≈' }, { color: getRandomColor(), text: '≠' }, { color: getRandomColor(), text: '≡' }, { color: getRandomColor(), text: '≤' }, { color: getRandomColor(), text: '≥' }, { color: getRandomColor(), text: '⊂' }, { color: getRandomColor(), text: '⊃' }, { color: getRandomColor(), text: '⊄' }, { color: getRandomColor(), text: '⊆' }, { color: getRandomColor(), text: '⊇' }, { color: getRandomColor(), text: '⊕' }, { color: getRandomColor(), text: '⊗' }, { color: getRandomColor(), text: '⊥' }, { color: getRandomColor(), text: '⋅' }, { color: getRandomColor(), text: 'Α' }, { color: getRandomColor(), text: 'Β' }, { color: getRandomColor(), text: 'Γ' }, { color: getRandomColor(), text: 'Δ' }, { color: getRandomColor(), text: 'Ε' }, { color: getRandomColor(), text: 'Ζ' }, { color: getRandomColor(), text: 'Η' }, { color: getRandomColor(), text: 'Θ' }, { color: getRandomColor(), text: 'Ι' }, { color: getRandomColor(), text: 'Κ' }, { color: getRandomColor(), text: 'Λ' }, { color: getRandomColor(), text: 'Μ' }, { color: getRandomColor(), text: 'Ν' }, { color: getRandomColor(), text: 'Ξ' }, { color: getRandomColor(), text: 'Ο' }, { color: getRandomColor(), text: 'Π' }, { color: getRandomColor(), text: 'Ρ' }, { color: getRandomColor(), text: 'Σ' }, { color: getRandomColor(), text: 'Τ' }, { color: getRandomColor(), text: 'Υ' }, { color: getRandomColor(), text: 'Φ' }, { color: getRandomColor(), text: 'Χ' }, { color: getRandomColor(), text: 'Ψ' }, { color: getRandomColor(), text: 'Ω' }, { color: getRandomColor(), text: 'α' }, { color: getRandomColor(), text: 'β' }, { color: getRandomColor(), text: 'γ' }, { color: getRandomColor(), text: 'δ' }, { color: getRandomColor(), text: 'ε' }, { color: getRandomColor(), text: 'ζ' }, { color: getRandomColor(), text: 'η' }, { color: getRandomColor(), text: 'θ' }, { color: getRandomColor(), text: 'ι' }, { color: getRandomColor(), text: 'κ' }, { color: getRandomColor(), text: 'λ' }, { color: getRandomColor(), text: 'μ' }, { color: getRandomColor(), text: 'ν' }, { color: getRandomColor(), text: 'ξ' }, { color: getRandomColor(), text: 'ο' }, { color: getRandomColor(), text: 'π' }, { color: getRandomColor(), text: 'ρ' }, { color: getRandomColor(), text: 'ς' }, { color: getRandomColor(), text: 'σ' }, { color: getRandomColor(), text: 'τ' }, { color: getRandomColor(), text: 'υ' }, { color: getRandomColor(), text: 'φ' }, { color: getRandomColor(), text: 'χ' }, { color: getRandomColor(), text: 'ψ' }, { color: getRandomColor(), text: 'ω' }, { color: getRandomColor(), text: 'ϑ' }, { color: getRandomColor(), text: 'ϒ' }, { color: getRandomColor(), text: 'ϖ' }, { color: getRandomColor(), text: 'Œ' }, { color: getRandomColor(), text: 'œ' }, { color: getRandomColor(), text: 'Š' }, { color: getRandomColor(), text: 'š' }, { color: getRandomColor(), text: 'Ÿ' }, { color: getRandomColor(), text: 'ƒ' }, { color: getRandomColor(), text: 'ˆ' }, { color: getRandomColor(), text: '˜' }, { color: getRandomColor(), text: ' ' }, { color: getRandomColor(), text: ' ' }, { color: getRandomColor(), text: ' ' }, { color: getRandomColor(), text: '' }, { color: getRandomColor(), text: '' }, { color: getRandomColor(), text: '–' }, { color: getRandomColor(), text: '—' }, { color: getRandomColor(), text: '‘' }, { color: getRandomColor(), text: '’' }, { color: getRandomColor(), text: '‚' }, { color: getRandomColor(), text: '“' }, { color: getRandomColor(), text: '”' }, { color: getRandomColor(), text: '„' }, { color: getRandomColor(), text: '†' }, { color: getRandomColor(), text: '‡' }, { color: getRandomColor(), text: '•' }, { color: getRandomColor(), text: '…' }, { color: getRandomColor(), text: '‰' }, { color: getRandomColor(), text: '′' }, { color: getRandomColor(), text: '″' }, { color: getRandomColor(), text: '‹' }, { color: getRandomColor(), text: '›' }, { color: getRandomColor(), text: '‾' }, { color: getRandomColor(), text: '€' }, { color: getRandomColor(), text: '™' }, { color: getRandomColor(), text: '←' }, { color: getRandomColor(), text: '↑' }, { color: getRandomColor(), text: '→' }, { color: getRandomColor(), text: '↓' }, { color: getRandomColor(), text: '↔' }, { color: getRandomColor(), text: '↵' }, { color: getRandomColor(), text: '⌈' }, { color: getRandomColor(), text: '⌉' }, { color: getRandomColor(), text: '⌊' }, { color: getRandomColor(), text: '⌋' }, { color: getRandomColor(), text: '◊' }, { color: getRandomColor(), text: '♠' }, { color: getRandomColor(), text: '♣' }, { color: getRandomColor(), text: '♥' }, { color: getRandomColor(), text: '♦' } ] }; }, methods: { onNavigationButtonTap() { frameModule.topmost().goBack(); }, onItemTap(item) { console.log('onItemTap'); } }, created() { console.log('listView sample created'); }, beforeDestroy() {} }); </script> My small worry is that even though I tested a lot of different symbols, I don't know if there is anything else that would break the rendering. From my end in the app I can replace the breaking symbols ( I have tried looking at the code to understand where the error might be coming from but I'm not sure. My guess is that it is linked to the logic in here: https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/Font.java#L312. The |
@dangrima90 thanks for investigating this. The issue clearly comes from the html parser https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/HtmlToSpannedConverter.java. It is modified code based on what you can see on the web. Clearly & and < (mostly > too) breaks the parser. Not sure why though |
@dangrima90 stumbled upon this today. smart-fun/XmlToJson#24 |
@farfromrefug thanks for the above - I have been testing with HTML Entities names and got somewhere but not 100% a full proof solution. For some reason in ns preview using For my use case I've been trying to use a regex to handle the replacing of these characters. The idea was to simply find Similar to the stackoverflow post in the issue you linked above, I found a similar explanation re: XML invalid characters: https://stackoverflow.com/a/28152666. Long story short it mentions that My question would be this: Not sure if it would be possible that whilst building the HTML string (https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/HtmlToSpannedConverter.java) it would check for any characters that should be escaped and it would handle that accordingly. Just an educated guess here, maybe something like the following will cater for this issue? @Override
public void characters(char ch[], int start, int length) throws SAXException {
StringBuilder sb = new StringBuilder();
/*
* Ignore whitespace that immediately follows other whitespace; newlines count
* as spaces.
*/
for (int i = 0; i < length; i++) {
char c = ch[i + start];
if (c == ' ' || c == '\n') {
char pred;
int len = sb.length();
if (len == 0) {
len = mSpannableStringBuilder.length();
if (len == 0) {
pred = '\n';
} else {
pred = mSpannableStringBuilder.charAt(len - 1);
}
} else {
pred = sb.charAt(len - 1);
}
if (pred != ' ' && pred != '\n') {
sb.append(' ');
}
} else {
switch(c) {
case "&":
sb.append("&");
break;
case "<":
sb.append("<");
break;
case ">":
sb.append(">");
break;
case "'":
sb.append("’");
break;
case "\"":
sb.append(""");
break;
default:
sb.append(c);
break;
}
}
}
mSpannableStringBuilder.append(sb);
} |
If the demo apps cannot help and there is no issue for your problem, tell us about it
Demo via NS Preview: https://stackblitz.com/edit/nativescript-stackblitz-templates-ipbbwj?file=app%2Fcomponents%2FHome.vue
Which platform(s) does your issue occur on?
ReferenceError: UILabelLinkHandlerTapDelegate is not defined
(not sure if it's an NS Preview issue). However when testing in the application I'm working on I saw the same behaviour.Please, tell us how to recreate the issue in as much detail as possible.
The issue is that HTML is not rendered properly when including ampersands in the text. Example:
I've tried using HTML Entities instead of the & symbol on its own but it resulted in the same thing.
I've included other examples in the NS Preview link above.
The text was updated successfully, but these errors were encountered: