-
-
Notifications
You must be signed in to change notification settings - Fork 588
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
Whitespace handling differs from HTML significantly (no collapsing, newlines ignored) #118
Comments
Hi, thanks for the thorough report. I didn't notice this. I'd love it if you could take a stab at it and tell us what you come up with. Depending on how much bloat this would add to the code, we can decide if we add it as a default behavior, or if we simply document this issue and provide an example of how to fix it. |
This is the result I’m getting for a HTML string with lots of whitespace, first with no special processing and then with a custom The result is not as complete as what HTML does, for instance in the case of The render part for this test: const testContent = `
a
e
<div> foo\n\nbar baz </div> <div>zzz</div>
<div>
<div>
<div>
<blockquote>
Salut<a href="#"> les copains </a> ,
<span>comment ça va ?</span>
</blockquote>
</div>
</div>
</div>
`
return (
<View>
<View style={borderStyle}>
<HTML html={testContent} />
</View>
<View style={borderStyle}>
<HTML html={testContent} alterData={collapseHtmlText} />
</View>
</View>
) Where |
@Exilz The current whitespace handling has bugs too: return <HTML html="<p>This <span>is</span> <strong>buggy</strong></p>" /> Shows:
You probably have a rule that a whitespace-only text node between two tag siblings can be dropped, but if the tags are both inline it should be kept (and collapsed to a single space if needed). If you can point me to the right source files, I can have a look and maybe do a PR. :) |
These parts in HTML.js are probably wrong: if (type === 'text') {
if (!strippedData || !strippedData.length) {
// This is blank, don't render an useless additional component
return false;
}
// Text without tags, these can be mapped to the Text wrapper
return {
wrapper: 'Text',
data: data.replace(/(\r\n|\n|\r)/gm, ''), // remove linebreaks
attribs: attribs || {},
parent,
parentTag: parent && parent.name,
tagName: name || 'rawtext'
};
}
Use case:
Use case:
|
My current solution uses this module: Which I’m using in alterData in this way: <HTML html={content} alterData={node => {
const newData = collapseText(node)
// return undefined to skip changing node text
return newData !== node.data ? newData : undefined
}} /> Of course it cannot fix the two issues highlighted in the previous comment, but it does handle the leading whitespace and uncollapsed whitespace issues. |
I have seen that the space is removed not only for strong tag but even for em, s and u. For example: |
@Draccan yup, these tags use the same logic as the ones fvsch pointed out. @fvsch your solution in your gist looks pretty clean. It feels like a solid improvement, even if it's obviously not matching an actual browser rendering. I'll try it out more, and figure out whether if this can be added in the codebase by default. I'll measure the performances impact and the potential regressions (all help is welcome here !) and if everything is going smoothly, let's add it to the project. What do you think ? |
Sounds like a good plan. And if there a risk it can change rendering significantly for library users, it could be a semver-major change anyway. |
Is a big problem the space between the tag :(
|
I think that now the best solution is to understand what kind of HTML you receive. We are lucky because in the app we are developing the admin panel gives the possibility to enter text with bold, italic, paragraphs, etc. So the HTML editor is an our component and we know how it puts HTML tags. If you're lucky like us you can use something like: `
` Our editor puts spaces after tag closure and we put them before the tag closure in our app. If you're taking html pages from web I don't recommend to use this approach and especially avoid regex! |
@Draccan this is a good idea! but work stange.... if use a constat work fine `const htmlContent = 'Abbiamo completato l'installazione di tutto il pavimento in autobloccanti della 1a. Tappa della Smart City. Sono stati installati 188.000 m² di pavimento di alta qualità, la cui produzione proviene da SG Premoldados, installata nel nostro Polo Impresarial'; `if i use the dynamic content with the same structure your function doesn't work :( so strange `<HTML html={this.addSpaceToHtml(notice.content)}
|
@robertobrogi Al momento noi abbiamo un endpoint Firebase che ci restituisce un oggetto. Tra le proprietà di questo oggetto abbiamo "description" la quale contiene HTML. Non faccio altro che passargli il contenuto di quella proprietà. Potresti provare a chiamare addSpaceToHtml in componentWillReceiveProps, nel costruttore o al mount e non direttamente sul componente HTML? Se non funziona così non so bene come aiutarti 🍡 |
@Draccan non funziona... sembra una cosa così banale... non capisco cosa non sta funzionando |
@robertobrogi Magari fatti stampare l'output in console della stringa HTML risultante, è possibile che avvenga qualcosa di particolare (i tag sono tutti aperti e chiusi correttamente? c'è qualche errore nella stringa html?). Se vuoi invia l'errore così magari provo a dare un'occhiata. Sarebbe utile anche la sorgente HTML che stai usando se possibile. We will publish the solution, if we find it, in english |
i make a call api and i have a news map: RENDER:
before Your function: after after your function: maybe is the wrong regex? |
life is strange .... :) now works! the problem was thew regex: is: and NOT without **space/g work fine... |
Ok! I've used the space after the tag closure because of this scenario: if I have So I don't want to have a space between strings if the 2 tags are attached. |
For the problem where <HTML html={myHtmlContent.replace(/\r?\n/g, ' ')} /> |
I noticed that the whitespace was being rendered unlike with HTML so I took a crack at filtering the content with an alterData like so:
Seems to be much better now. Though it might not be foolproof/bug-free. |
@djpetenice same problem here. If the content is (with space between <p><a href="abc">abc</a> <a href="def">def</a></p> It renders (without space):
|
I did a hack by adding a span with a single character and styling it the same colour as my background. |
Based on @djpetenice genius idea, I created this function: export const fixHtmlBlockSpaces = (str = '') => {
const fixedStr = str.replace(/(<\/[^>]+>)\s+(<)/gm, (substring, group1, group2) => {
return `${group1}<span style="color: transparent">_</span>${group2}`;
});
return fixedStr;
}; Now this: <p><a href="abc">abc</a> <a href="def">def</a></p> Is replaced by this: <p><a href="abc">abc</a><span style="color: transparent">_</span><a href="def">def</a></p> |
@douglasjunior Your example works for me. But one problem its takes too space than normal space. Need more better solution from library. |
I also getting error on emoji image. I put below content:
Expected Behaviour : Plz suggest any solution. |
Any update on this happening? |
Finally I just switched to react-native-htmlview. |
@Exilz is there any solution for image render problem? |
Jajajajajaja thinking so seriously to do the same and add a style in web to make it look similar. |
Are there any plans to resolve this issue any time soon? Or are workarounds the recommended solution at the moment? Thanks |
One possible workaround I've found, although I can't vouch for it as I haven't tested it fully, is tricking the library into thinking that the text node is not fully whitespace. This seems to prevent the node from being collapsed. Here I add a zero-width character to whitespace data: alterData: node => {
if (node.data.match(/\s+/)) {
return `${data}\u200C`
}
} In the cases I've seen, this seems to stop the whitespace from being lost. However I'm not sure if there's other impact. |
Applying the following replace function to data before passing it to the component works for all our content so far:
|
A few tests fail, confirming that the current behavior is not compliant with HTML specs. covers #118
I've done some research to see where those collapsing rules are specified. It appears to be the CSS rule Full Reference
Glossary
But this reference considers multiple contexts that we can ignore in a minimal compatibility approach. The reference describes the required behavior for multiple values of the
The W3C consortium also provides a gigantic test suite, and one folder is specifically dedicated to CSS whitespaces which can be a source for inspiration. In the meantime, I have started to implement some basic tests regarding whitespaces, see 53b8679 and d76f99d. A majority of them fail, of course, which is the point of this issue! |
I've just written a RFC to fix this issue in an upcoming version. You can find it here! |
@fvsch what was the module that you use? |
I am currently developing this behavior as part of a service for Expensify. The new engine following the whitespace RFC is being implemented here: https://github.com/native-html/core. An early release should be available in the upcoming week. This pre-release will be part of the 6.x release cycle. If you are wondering why we're jumping from 4 to 6, the reason is that 6.x will require more recent versions of React Native, and we want all users to benefit from the 5.x enhancements already available in alpha. Also, the new engine changes the structure of nodes available with |
I've made great progress with the new release! Given this snippet: <span>This is text!</span>
This is <strong>bold</strong> <em>italics</em>. We now have:
You will be able to control the whitespace behavior with the special |
|
Is this a bug report or a feature request?
Bug report. Though fixing this might change the behavior of this lib too much for users, so the solutions are probably to write documentation and/or provide an opt-in fix.
Have you read the guidelines regarding bug report?
Yes.
Have you read the documentation in its entirety?
Yes.
Have you made sure that your issue hasn't already been reported/solved?
Yes, to the best of my abilities. :)
Is the bug specific to iOS or Android? Or can it be reproduced on both platforms?
Both platforms.
Is the bug reproductible in a production environment (not a debug one)?
Sorry, have not tried yet in a production build. I expect the same result though.
Have you been able to reproduce the bug in the provided example?
Have not tried, but the issue has a really simple setup so it shouldn’t differ.
Environment
Environment:
Target Platform:
Steps to Reproduce
Render this JSX:
Expected Behavior
I expected react-native-render-html to handle whitespace collapsing similarly to what HTML does. Replacing a rendered space character (U+0020 SPACE) with
•
, that would be:Actual Behavior
react-native-render-html (3.9.0 and master) renders:
What seems to work:
What seems broken:
I suspect this lib is limited by React Native’s Text component and errs on the side of not manipulating text too much, only removing newlines?
If that is the case, I can think of two possible improvements:
I’m going to implement some fixes on our side using simple regexps on our HTML. I can post what I come up with here if that’s useful. Or maybe I should do it in alterData for more fine-grained control?
The text was updated successfully, but these errors were encountered: