Angular Markdown Parsing "\n" Newline Characters Issue - javascript

I've created a blog where markdown is returned as a string from my backend, however when I return a string with the correct newline characters it does not behave as expected.
I am using ngx-markdown to handle parsing of markdown characters, and using the ngPreserveWhitespaces attribute to ensure this should be functioning as expected.
Example:
// Example #1 Returned String
"## This is a subheader\n This is a sentence"
// Output
<h2>This is a subheader\n This is a sentence</h2>
It displays it as a single line with the newline character physically rendered as text, as above.
However within any of my Angular components I can literally write this same string as a property on the component and return it, and it renders correctly like so:
// Example #2 Hard Coded String
public correct: string = "## This is a subheader\n This is a sentence";
// Output
<h2>This is a subheader</h2>
<p>This is a sentence</p>
As mentioned, the markdown parser I am using is implemented as such:
<markdown ngPreserveWhitespaces>{{content}}</markdown>
I have also attempted to do this by setting ngPreserveWhitespaces within the main/tsconfig files. However I do not believe this is what the issue is, as I can (natively in JS) console.log both my returned string (#1) and the hard coded string (#2) and even my damn logs display differently (with the latter formatting correctly and the former just stringifying the output).
I have attempted:
JSON stringify/parsing the data in multiple ways (as well as without)
I have attempted using regex to manually replace characters
I have attempted to just manually use <br />
I have tried everything outlined here regarding this markdown parser handling whitespace (which I do not believe is the issue)
Nothing appears to appease the newline gods.

Solution
Okay so I've found my solution to this, I am now storing my markdown string as such:
"## This is a subheader\n This is a sentence"
This difference here is the interface I'm storing this within (a Mongo db) puts the speechmarks around string values already, so it now actually looks like this:
""## This is a subheader\n This is a sentence""
Which is more a weird thing with MongoDB Compass than with what I was attempting.
From this, I am able to JSON.parse the value correctly (previously it was attempting to do so with a string that wasn't valid JSON as it wasn't enclosed in double speechmarks).
I am now handling this in an extension of a Property class I have for each of these called HtmlProperty which when instantiated, parses the value correctly.

Related

Weird symbol in string breaks JSON.parse, but seems to be undetectable?

The description field is a text area field, somehow a user ended up with some strange little symbol in it. (see image)
When I grab this from the server, I assemble my data from the objects I grab, which includes the description on this object, and turn it into JSON string, and send it to my javascript.
From javascript, I JSON.parse it. But that weird little symbol causes the parse to fail. But, when you look at it, there is no character there or anything, yet it throws an undefined character in JSON.parse.
My response from the server has the description like this:
"blahblahtesttext\r\nslkdjf",
There is nothing but the expected \r\n......
But it has an unexpected token where that symbol is.
{"value":"blah blah test text//Symbol should be here, but there is nothing and it forces it to the next line
\r\nslkdjf","fieldType":"TEXTAREA","field":"Description"}
Where that symbol forces the string to the next line, which causes the issue.
Because I can't see what the actual character is... I do not know how to handle this.
Is there something that can strip out invalid characters in a JSON string so the parse works? I don't want to just try/catch this as it would toss out everything, I just want that weird invalid symbol to be stripped out.
Or is there a way to see what the actual character is that JSON.parse does not like?

 <-- here is that symbol for copy pasting into a string if you want to try parsing it.
EDIT:
I found that it was doing this in Notepad++
Where you can see that where the line separator was, it is placing actual carriage return and line feed there, breaking the string. It already has \r\n\r\n for the two returns that were placed in the actual text area after that line separator character.
But still unsure of how to deal with this, as that carriage return and line feed do not appear in the string as '\n\r', there is no character representation of them, but instead it actually puts a return there and breaks the string.
NEW EDIT:
Finally found something to get this working. I couldn't do a replace on that line separator character. When I pulled it from my database, it came through as a hidden carriage return. When you manually pressed 'Enter' in the text area, the string I got from the database would actually put a '\r\n' there. But the line separator did not.
So, I added these three lines before parsing to ensure I was escaping any invalid new lines/carriage returns.
result = result.replace(/\r\n/g, '\\r\\n');
result = result.replace(/\r/g, '\\r');
result = result.replace(/\n/g, '\\n');
The '\r\n' that were actually in the string would correctly be escaped already, which tripped me up because I didn't have to worry about escaping those until someone tried introducing this line separator....
As Xufox says, that appears to be U+2028. JSON.parse shouldn't fail on it since U+2028 doesn't require escaping in JSON; Chrome's doesn't, but that's probably because it's implementing this stage 4 proposal Xufox pointed out:
const o = {prop: "testing\u2028one two three"};
console.log(JSON.parse(JSON.stringify(o)));
If you need to work around a JSON.parse implementation that doesn't handle it, you could do this:
str = str.replace(/\u2028/g, "\\u2028");
...before running JSON.parse on str.

Matching a JS string with regex

I have a long xml raw message that is being stored in a string format. A sample is as below.
<tag1>val</tag><tag2>val</tag2><tagSomeNameXYZ/>
I'm looking to search this string and find out if it contains an empty html tag such as <tagSomeNameXYZ/>. This thing is, the value of SomeName can change depending on context. I've tried using Str.match(/tagSomeNameXYZ/g) and Str.match(/<tag.*.XYZ\/>/g) to find out if it contains exactly that string, but am able to get it return anything. I'm having trouble in writing a reg ex that matches something like <tag*XYZ/>, where * is going to be SomeName (which I'm not interested in)
Tl;dr : How do I filter out <tagSomeNameXYZ/> from the string. Format being : <constant variableName constant/>
Example patterns that it should match:
<tagGetIndexXYZ/>
<tagGetAllIndexXYZ/>
<tagGetFooterXYZ/>
The issue you have with Str.match(/<tag.*.XYZ\/>/g) is the .* takes everything it sees and does not stop at the XYZ as you wish. So you need to find a way to stop (e.g. the [^/]* means keep taking until you find a /) and then work back from there (the slice).
Does this help
testString = "<tagGetIndexXYZ/>"
res = testString.match(/<tag([^/]*)\/\>/)[1].slice(0,-3)
console.log(res)

How to assign large string to a variable without ILLEGAL Token error?

I need to assign a long string (4 pages worth of text) to a variable, so far I've been doing it like this
var myText = "[SOME] Text goes \
.. here ? and 'there' \
is more ( to \
come etc. !)";
slashes at the end need to be added to all of the text, and I can't imagine how long this will take to do manually. Also, I get ILLEGAL error for some reason I don't understand for the first line.
Therefore I wanted to find out the best way to handle this situation. I was looking into solutions of passing in a .txt file, but would rather do it as a really long string (this is not a production app). Also string shown in example is random, showing that there can be a lot of various characters in it that need to be accounted for.
You have to concatenate the string:
var t = ""
+"text line 1"
...
+"text line n"
But I would put the text in a text file and read it using xhr (on client) or io (on server).
You cannot have a multiline string definition in javascript but you have several options :
save your text in a file and read this file from your program
use the multiline npm module which propose a hack to use function comments as multiline string definitions
use ES6 multi-line template strings notation, which have multi-line support - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings#Multi-line_strings
saving the text in a file would seem to me as the preferred option in your case since the text seem to be very long an potentially coming from an untrusted source. You do not want the pasted text to close the string and start doing innapropriate function calls.

From php json_encode to jquery decode

Im using a well known "hack" (the json encode function) to prevent some characters to mess up my html, im receiving from an API a description field that can content single or double quotes (and other special chars). So:
<div class="someThing" data-fulldescription=<?=json_encode($textFromApi);?>>
...
</div>
Now I read that data field using jquery and then print it inside a div:
$('#brand-modal-content').html($(this).parents('.someThing').data('fulldescription'));
The problem is, the quotes are now coded by the PHP function, and some characters get replaced by "\u00e8" or "\u00f9", is there a way to reformat the text using jquery?
You are injecting content into HTML in a very wrong (and even unsafe) way. Do this instead:
data-fulldescription="<?=htmlspecialchars(json_encode($textFromApi));?>"
This way the JSON will be properly encoded and safely injected no matter what is inside; then, you can decode it like so:
var decoded = JSON.parse($(this).parents('.someThing').data('fulldescription'));
The combination of these steps will perfectly preserve the JSON no matter what it represents (you can take shortcuts if you assume it's a string, but why not be always 100% safe?). You can then do whatever you want with the decoded value.

How do I insert HTML into Mongodb?

I keep getting kicked out of the shell when I try to paste in an HTML text file. How can this be done? Do I first need to use some javascript to encode it or something?
Example:
db.test.insert({x:"<div id='product-description'><p>Who hasn’t wished for a mini-Roomba to handle the arduous task of cleaning their iPhone screen? Now your dreams have come true!</p> <p>See the Takara web page for a <a href='http://www.takaratomy.co.jp/products/automee/' title='automee s' target='_blank'>demo video.</a></p>
<p><strong>Colors: </strong> White, Red, Orange and Blue<br>
Runs on a single AA battery.</p>
<p>1,575 yen</p><!-- end #product-description --></div>"})
EDIT
I put only single quotes inside my html and wrapped the whole thing in double-quotes, but still no good. shell error:
> j = ({z:"<div id='product-description'><p>Who hasn
---
Unicode text could not be correctly displayed.
Please change your console font to a Unicode font (e.g. Lucida Console).
---
’
bye
You need to remove or encode the control characters in your string.
For example, paste your text in here, and encode to UTF-8 ECMAScript (which means javascript strings).
ps: here an article about strings in javascript. tells you what needs escaping. http://docstore.mik.ua/orelly/webprog/jscript/ch03_02.htm
rompetroll provided some good references to get started. I too found a good solution online which works fine:
Link
But I think there is still some confusion regarding "displaying html back to browser from db". So, following are the steps which removes this confusion :
Step 1: Store html in mongodb
Mongo store everything in form of object. Basically convert your html into utf-8 or ASCII complied string and then store it to mongo.
<div>hi!</div> [from]
<div>hi!</div> [to UTF-8]
Step 2: Display html to browser
This is the step which is the source of confusion to some. People often forget to convert string back to html before displaying it to browser.
You have to decode your html using the same method you used for encoding.
<div>hi!</div> [output from mongo (decode it to html)]
<div>hi!</div> [browser output of above string]
(browser will read it as string and display as it is and not html(hi!) and hence needs to be decoded)
Link that I have provided have reference for both the steps.
Hope this will help
Cheers :)
Use compass, you don't need to encode. Studio3T editor also works, but you need a license.
To add html through MongoDB console, you need to escape your string.
Use this: https://www.freeformatter.com/json-escape.html#ad-output
Steps
copy HTML
go to the link above, paste HTML click on "Escape"
copy the Escaped HTML
Insert HTML (e.g: db.Emails.updateMany({name: 'email/seller'}, {$set: {template: "<!DOCTYPE html\">\r\n<html lang=\"en\"> ..."}})

Categories

Resources