jsPDF-AutoTable
jsPDF-AutoTable copied to clipboard
Option to parse HTML without removing newlines
I have a table where every other row is user-input that comes from a textarea, meaning the lines are separated using \n
rather than <br>
. I see below that you are stripping \n
but replacing <br>
with \n
afterwards.
https://github.com/simonbengtsson/jsPDF-AutoTable/blob/30d4138f97e7da52544d525ccbd1aebf03acb648/src/htmlParser.ts#L92-L100
I understand the reasoning behind this decision, but it would be nice to have the option to preserve the original line breaks. As it stands, I have to replace \n
in my text with <br>
only for it to be swapped back under the hood.
True! You mean you have a textarea
inside of the html table? If so I think there are two good options we can take:
- Handle textareas in a special way when parsing the html. Would love to merge a pull request for this.
- Recommend user to use didParseCell to parse the textarea content manually
I have content that comes from a <textarea>
. Currently I'm just rendering it straight into the table cell, but it wouldn't be too bad to put it in a <textarea>
. Originally I was thinking it would be easiest just to give the autotable()
some boolean flag telling it whether or not the input is formatted.
In that case, would it make sense to instead just skip over text within a <pre>
tag? That might align more with the original philosophy of looking how it would if it was HTML.
Got it! Yes I think the goal for autotable should be to make it look like the HTML as closely as possible meaning linebreaks etc would not show up. I don't know how it handles <pre>
tags today, but I would assume we would need to update the HTML parsing for it to parse pre
tags correctly.
A quick test shows that <pre>
has the desired effect in some but not all situations:
<pre>multi\nline\ntext</pre>
multi\nline\ntext
<pre>multi
line
text</pre>
multi line text
<pre>multi<br>line<br>text</pre>
multi line text
Using Vue.js, with multilineText === 'multi\nline\ntext'
,
<pre>{{ multilineText }}</pre>
multi line text
With multilineText === 'multi<br>line<br>text'
,
<pre>{{ multilineText }}</pre>
multi<br>line<br>text
Within autotable, the newline characters are removed, so all of the above options result in "multilinetext" (no line break or space) being rendered into the document.
An implementation of <pre>
which follows its raw HTML appearance exactly should:
- display HTML elements + entities from HTML source as usual
- display injected HTML as raw text (as in the last example)
- treat
\n
as two raw characters when it comes from HTML source - treat
\n
as a line break when it's injected (as in the fourth example) - render all text in the browser's default mono font
This adds up to be a lot and as far as I know, autotable has no way of knowing whether content was injected or not. That combined with the assumption that most users will prefer their multiline text in the document's font rather than mono, makes it seem counterproductive to actually implement <pre>
.
Instead, it might be more user-friendly to return to the idea I opened this issue with and give the user a boolean flag which they can use to indicate whether or not autotable should remove newlines from the string.
This does seem to be blown out of proportion just for the idea of removing a small redundancy, so I'd like to clarify it a little bit. At its core, the issue is that currently, to get line breaks with dynamic content, <br>
elements have to be used in the content. This creates the redundancy issue, but more importantly, if the content is permitted to have HTML elements in it, it's open to XSS attacks. This is the real driver behind me wanting to get this change done.
Sounds reasonable to me as well. The main question then is if this is best to add a new option for this or if it is enough to handle this case manually with didParseCell
. Have you tried that?
I'm having something of the same issue but I'm not sure I'm getting there the same way as @ga-jrich. Inside a didParseCell
, I have something along these lines:
if(data.column.index==3){
let cid = "#textarea-id-prefix"+data.row.index.toString();
try{
let cResult=document.querySelector(cid).value;
data.cell.text=cResult;
}
catch{er){console.log("No notes.")}
}
Replacing the newline \n with <br/>
results in the literal breakstring getting inserted into the text though.
Since the original issue doesn't seem to be using this method, did I overcomplicate things? Is there a solution that would work better for my use case?