I have a string:
<Grid><Description>LINE 1
LINE 2
LINE 3
LINE 4
</Description><</Grid>
I need it to be decoded with line breaks. I found solution:
function decodeString(stringToDecode) {
if (!stringToDecode) {
return stringToDecode;
}
return $('<div />').html(stringToDecode).text();
}
But it makes single line and replaces all the line breaks with spaces.
you may use the following to replace your line breaks with <br /> tags an then set the HTML:
return $('<div />').html(stringToDecode.replace(/\n/, '<br />')).text();
function decodeString(stringToDecode) {
return stringToDecode ? $('<div />').html(stringToDecode.replace(/[\n\r]/g, "<br> \r\n")).text() : ""
}
Your sample has CR/LF - but that is not a line break in HTML. You need to replace it with a valid HTML line break ie the < br > tag.
Your function has a strange if statement that does not make much sense. Why return stringToDecode when you've just proven it is null? Also, $('<div />').html(stringToDecode).text() will not do anything helpful.
Try something like this:
function decodeString(stringToDecode) {
if (!stringToDecode) {
return "";
}
var regX = /\\n/g;
var replaceString = '<br> \\n';
return stringToDecode.replace(regX, replaceString);
}
Related
Hey :) I know a similiar question was asked before, but i just cant get it through. I want to create a method called something like makeMeSpaces, so my h2 text will have a space between each character.. and i might want to use it elsewhere aswell. I have this until now, from the logic point of view:
var text = "hello";
var betweenChars = ' '; // a space
document.querySelector("h1").innerHTML = (text.split('').join(betweenChars));
it also works pretty fine, but i think i want to do
<h2>Hello.makeMeSpaces()</h2>
or something like this
Thank you guys!
If you really want this in a 'reusable function,' you'd have to write your own:
function addSpaces(text) {
return text.split('').join(' ');
}
Then, elsewhere in code, you could call it like so:
var elem = document.querySelector('h2');
elem.innerHTML = addSpaces(elem.innerHTML);
Maybe this is what you want , not exactly what you showed but some what similar
Element.prototype.Spacefy = function() {
// innerText for IE < 9
// for others it's just textContent
var elem = (this.innerText) ? this.innerText : this.textContent,
// replacing HTML spaces (' ') with simple spaces (' ')
text = elem.replace(/ /g, " ");
// here , space = " " because HTML ASCII spaces are " "
space = " ",
// The output variable
output = "";
for (var i = 0; i < text.length; i++) {
// first take a character form element text
output += text[i];
// then add a space
output += space;
};
// return output
this.innerHTML = output;
};
function myFunction() {
var H1 = document.getElementById("H1");
// calling function
H1.Spacefy();
};
<h1 id="H1">
<!-- The tags inside the h1 will not be taken as text -->
<div>
Hello
</div>
</h1>
<br />
<button onclick="myFunction ()">Space-fy</button>
You can also click the button more than once :)
Note :- this script has a flow, it will not work for a nested DOM structure refer to chat to know more
Here is a link to chat if you need to discuss anything
Here is a good codepen provided by bgran which works better
trying to parse some content (no DOM available - or DOM parser for that matter i.e. jQuery, Cheerio) to replace some words/symbols (basically emotions) by images, BUT would like to ignore everything in between <code></code> and <pre></pre> this example works great on replacing all the emotions, but doesn't ignore code and pre tags
http://jsbin.com/odARehI/5/edit?js,console
if you run the script, you will see the first print out before the code tag and the second after.
would appreciate another set of eyes on that pattern. Thanks
// see link for a list of the emotions to parse
var pattern = />:\)|\([\w~]+\)|\\[:]?[od]\/|[:;\|bBiIxX8\(\)\]][=\-"^:]?[)>$&|\w\(\)*##?]?[)>$&|\w\(\)*##?]/g;
I tried few things that didn't work without messing up the original match.
For the Don't-parse-html-with-regex-police-department: this is running server side and I do not have the luxury for a DOM parser at the moment.
Thank you.
UPDATE: for a RegExp solution to ignore <code> tags see this neat solution thanks to github/frissdiegurke in this commit
/(^|<\/code>)([^<]*|<(?!code>))*(<code>|$)/g
Without DOM parsing you are going to have edge cases which will fail. But, this should work for you.
Given this HTML:
Hello :) <pre>Wassup :)</pre> Maybe :) <code>:) Foo</code> :) Bar
Use this code:
var blocks = [];
html = html.replace(/(?:<pre>.*?<\/pre>|<code>.*?<\/code>)/g, function (match) {
blocks.push( match );
return '__BLOCK__';
});
html = html.replace(/:\)/g, 'SMILE');
html = html.replace(/__BLOCK__/g, function () {
return blocks.shift();
});
Which produces:
Hello SMILE <pre>Wassup :)</pre> Maybe SMILE <code>:) Foo</code> SMILE Bar
Just adjust the /:\)/g replace to work however you need it.
Guess you're using nodejs or a recent javascript engine (for "map" & "split" implementations), so you can do this:
function replaceSpecial(str, pattern, replacement) {
var REG = /(<code>.*?<\/code>)|(<pre>.*?<\/pre>)/i;
return str.split(REG).map(function(s) {
if ('' + s !== s)
return '';
if (s.match(REG))
return s;
return s.replace(pattern, replacement);
}).join('');
}
Example:
replaceSpecial("hey :) <code>:)</code> :'( <pre> :'( :)</pre>", /(:\))|(:'\()/, function(s) {
switch(s) {
case ":)":
return '<img src="smile.gif" />';
case ":'(":
return '<img src="cry.gif" />';
}
})
Will return:
"hey <img src="smile.gif" /> <code>:)</code> <img src="cry.gif" /> <pre> :'( :)</pre>"
Or easier if you just want to replace an emoticon:
replaceSpecial("hey :) <code>:)</code>", ":)", '<img src="smile.gif" />')
=>
"hey <img src="smile.gif" /> <code>:)</code>"
var co = -1, ce = 0, start=0, result;
while ( ce != -1 ) {
co = testString.indexOf('<code', ce);
if (co > -1) {
result += parse(testString.substring(start,co), pattern1);
start = co+1;
ce = testString.indexOf('</code>', co + 5);
if (ce >-1 ){
start = ce + 7;
ce = start;
result += testString.substring(co,ce);
}
}
}
result += parse(testString.substring(start), pattern1);
console.log(result);
I'm attempting to duplicate the original img tag's functionality in custom img tag that will be added to the pagedown converter.
e.g I'm copy the original behavior:
![image_url][1] [1]: http://lolink.com gives <img src="http://lolink.com">
into a custom one:
?[image_url][1] [1]: http://lolink.com gives <img class="lol" src="http://lolink.com">
Looking at the docs the only way to do this is through using the preblockgamut hook and then adding another "block level structure." I attempted doing this and got an Uncaught Error: Recursive call to converter.makeHtml
here's the code of me messing around with it:
converter.hooks.chain("preBlockGamut", function (text, dosomething) {
return text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, function (whole, inner) {
return "<img src=" + dosomething(inner) + ">";
});
});
I'm not very experienced with hooks and everything so what would I do to fix it? Thanks.
UPDATE: found out that _DoImages runs after prespangamut, will use that instead of preblockgamut
Figured it out! The solution is very clunky and involves editing the source code because I am very bad at regex and the _DoImage() function uses a lot of internal functions only in the source.
solution:
All edits will be made to the markdown.converter file.
do a ctrl+f for the _DoImage function, you will find that it is named in two places, one in the RunSpanGamut and one defining the function. The solution is simple, copy over the DoImage function and related stuff to a new one in order to mimic the original function and edit it to taste.
next to DoImage function add:
function _DoPotatoImages(text) {
text = text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writePotatoImageTag);
text = text.replace(/(\?\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writePotatoImageTag);
return text;
}
function writePotatoImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
var whole_match = m1;
var alt_text = m2;
var link_id = m3.toLowerCase();
var url = m4;
var title = m7;
if (!title) title = "";
if (url == "") {
if (link_id == "") {
link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
}
url = "#" + link_id;
if (g_urls.get(link_id) != undefined) {
url = g_urls.get(link_id);
if (g_titles.get(link_id) != undefined) {
title = g_titles.get(link_id);
}
}
else {
return whole_match;
}
}
alt_text = escapeCharacters(attributeEncode(alt_text), "*_[]()");
url = escapeCharacters(url, "*_");
var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
title = attributeEncode(title);
title = escapeCharacters(title, "*_");
result += " title=\"" + title + "\"";
result += " class=\"p\" />";
return result;
}
if you look at the difference between the new _DoPotatoImages() function and the original _DoImages(), you will notice I edited the regex to have an escaped question mark \? instead of the normal exclamation mark !
Also notice how the writePotatoImageTag calls g_urls and g_titles which are some of the internal functions that are called.
After that, add your text = _DoPotatoImages(text); to runSpanGamut function (MAKE SURE YOU ADD IT BEFORE THE text = _DoAnchors(text); LINE BECAUSE THAT FUNCTION WILL OVERRIDE IMAGE TAGS) and now you should be able to write ?[image desc](url) along with ![image desc](url)
done.
The full line (not only the regex) in Markdown.Converter.js goes like this:
text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
so check the function writeImageTag. There you can see how the regex matching text is replaced with a full img tag.
You can change the almost-last line before its return from
result += " />";
to
result += ' class="lol" />';
Thanks for the edit to the main post.
I see what you mean now.
It is a bit weird how it uses empty capture groups to specify tags, but if it works, it works.
It looks like you would need to add on an extra () onto the regex string, then specify m8 as a new extra variable to be passed into the function, and then specify it as class = m8; like the other variables at the top of the function.
Then where it says var result =, instead of class =\"p\" you would just put class + title=\"" + .......
Please consider the following HTML <pre> element:
This is some
example code which
contains tabs
I would like to replace all of the tab characters with four non-breaking space characters in HTML (i.e. ). I have tested the above pre element with JavaScript for the presence of tab characters as follows:
$('pre').ready(function() {
alert(/\t/.test($(this).text()));
});
But it is always returned false. Can anyone tell me the correct process by which to replace tab spaces from the source code to HTML NBSPs? The tabs have been added by Komodo Edit, and are visible when viewing the source.
You can do it like this:
$('pre').html(function() {
return this.innerHTML.replace(/\t/g, ' ');
});
That will loop through all pre elements on the page and call the function for each of them. jQuery's html function uses the return value of the function we give to replace the content of each element. We're using String#replace to replace all (note the g flag on the regexp) tab characters in the HTML string with four non-breaking spaces.
Live example
It removes line breaks, extra spaces and line breaks:
function removeNewlines(str) {
//remove line breaks from str
str = str.replace(/\s{2,}/g, ' ');
str = str.replace(/\t/g, ' ');
str = str.toString().trim().replace(/(\r\n|\n|\r)/g,"");
console.log(str);
}
Demo:
function removeNewlines(str) {
//remove line breaks from str
str = str.replace(/\s{2,}/g, ' ');
str = str.replace(/\t/g, ' ');
str = str.toString().trim().replace(/(\r\n|\n|\r)/g,"");
console.log(str);
}
$('#acceptString').click(function() {
var str = prompt('enter string','');
if(str)
removeNewlines(str)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='button' value='Enter String' id='acceptString' />
Try this:
var tab = RegExp("\\t", "g");
document.getElementById("text").value =
document.getElementById("text").value.replace(tab,' ');
In IE when I insert text into a <pre> tag the newlines are ignored:
<pre id="putItHere"></pre>
<script>
function putText() {
document.getElementById("putItHere").innerHTML = "first line\nsecond line";
}
</script>
Using \r\n instead of a plain \n does not work.
<br/> does work but inserts an extra blank line in FF, which is not acceptable for my purposes.
These quirksmode.org bug report and comments about innerHTML behaviour of Internet Explorer could help:
"IE applies HTML normalization to the data that is assigned to the innerHTML property. This causes incorrect display of whitespace in elements that ought to preserve formatting, such as <pre> and <textarea>."
Does this work in IE?
document.getElementById("putItHere")
.appendChild(document.createTextNode("first line\nsecond line"));
I tested it with Firefox and it works. :-)
The workaround can be found in the page linked to in the accepted answer. For ease of use here it is:
if (elem.tagName == "PRE" && "outerHTML" in elem)
{
elem.outerHTML = "<PRE>" + str + "</PRE>";
}
else
{
elem.innerHTML = str;
}
<br/> shoud only output one line in all browsers. Of course remove the \n as well, code should be:
document.getElementById("putItHere").innerHTML = "first line<br/>second line";
Content inside the <pre> tag should not be considered HTML.
In fact, the point of <pre> tag is so that it does display formatted text.
Using the innerText property is the correct way to modify the content of a <pre> tag.
document.getElementById("putItHere").innerText = "first line\nsecond line";
IE9 does not normalize white spaces, unlike its predecessors.
You should test for support rather than targeting any specific browser. E.g...
var t = document.createElement(elem.tagName);
t.innerHTML = "\n";
if( t.innerHTML === "\n" ){
elem.innerHTML = str;
}
else if("outerHTML" in elem)
{
elem.outerHTML = "<"+elem.tagName+">" + str + "</"+elem.tagName+">";
}
else {
// fallback of your choice, probably do the first one.
}
I reckon this.
What I found was IE is using \r\n and Fx(others) is using \n
var newline;
if ( document.all ) newline = '\r\n';
else newline = '\n';
var data = 'firstline' + newline + 'second line';
document.getElementById("putItHere").appendChild(document.createTextNode(data));
For a TinyMCE(wysiwyg editor) plugin I once made I ended up with using BR i edit mode
and cleaned it up on submit etc.
This code loops through all BR elements inside PRE elements and replaces BR with newlines.
Note that the code relies on the TinyMCE API, but can easily be written using standard Javascript.
Clean up:
var br = ed.dom.select('pre br');
for (var i = 0; i < br.length; i++) {
var nlChar;
if (tinymce.isIE)
nlChar = '\r\n';
else
nlChar = '\n';
var nl = ed.getDoc().createTextNode(nlChar);
ed.dom.insertAfter(nl, br[i]);
ed.dom.remove(br[i]);
}
Good luck!
If you don't want to use outerHTML, you can also do the following for IE, if an additional pre tag is not an issue:
if(isIE)
document.getElementById("putItHere").innerHTML = "<pre>" + content+"</pre>";
else
document.getElementById("putItHere").innerHTML = content;
I've found that innerHTML is processed before it is applied to the element, hence <br> becomes a newline and multiple white spaces are removed.
To preserve the raw text you must use nodeValue, for example;
document.getElementById('pre_id').firstChild.nodeValue=' white space \r\n ad new line';
Here is a very small tweak to Edward Wilde's answer that preserves the attributes on the <pre> tag.
if (elem.tagName == "PRE" && "outerHTML" in elem) {
var outer = elem.outerHTML;
elem.outerHTML = outer.substring(0, outer.indexOf('>') + 1) + str + "</PRE>";
}
else {
elem.innerHTML = str;
}
if (typeof div2.innerText == 'undefined')
div2.innerHTML = value;
else
div2.innerText = value;
that worked for me.