I'm trying to make a class to convert bbcode to html but replace doesn't call callback function.
Here's what i have
function bbcode(){
this.bbcode_table = {};
this.bbcode_table[/[asdf]/g] = function(match, contents, offset, input_string){
return "hi";
}
}
bbcode.prototype.toHTML = function(str){
for (var key in this.bbcode_table){
str = str.replace(key, this.bbcode_table[key]);
}
console.log(str); // asdf
}
var a = new bbcode;
a.toHTML("asdf");
The code above is not working, however, the code below works well.
text = "asdf";
text = text.replace(/[asdf]/g, function(match, contents, offset, input_string){
return "hi";
});
console.log(text); // hihihihi
What am I doing wrong?
Because the key is converted to string, so the funtion replace is not capturing any match with "/[asdf]/g".
You can follow this approach with the object RegExp
function bbcode() {
this.bbcode_table = {};
this.bbcode_table["[asdf]"] = {
"cb": function(match, contents, offset, input_string) {
return "hi";
},
"flag": "g"
}
}
bbcode.prototype.toHTML = function(str) {
for (var key in this.bbcode_table) {
var regex = new RegExp(key, this.bbcode_table[key].flag);
str = str.replace(regex, this.bbcode_table[key].cb);
}
console.log(str);
}
var a = new bbcode;
a.toHTML("asdf");
Related
I have the following function:
function parseEntry(query, html, url) {
// logic draft :(
var re = new RegExp('{{{(.*)}}}');
regex = query.replace(re, "$1");
var newre = new RegExp(regex);
regged = html.replace(newre, "$1");
ret = query.replace(regex, regged);
// parse selectors
var re = new RegExp('{{(.*)}}');
newtext = html.replace(re, "$1");
ret = ret.replace(newtext, $(newtext).clone().html());
// parse %url%
ret = ret.replace("%url%", url);
// ret remaining
return ret;
}
// Called this way:
let output = parseEntry('static value %url% {{.thisclass}} {{{(\d+)}}}', '<h1 class="thisclass">Test</h1><h2 class="thisclass">Test2</h2> 1234 12', "http://perdu.com");
console.log(output)
/**
should return:
static value http://perdu.com TestTest2 123412
{{{triple brackets = regex}}}
{{double brackets = jquery}}
**/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Can you help refactoring parseEntry() function to return expected output?
All help appreciated!
I'm not sure if I undersand, but this is an attempt using different approaches I think are useful in this kind of situations. There are examples of split(), replace() and the createElement hack to parse html.
var query = 'static value %url% {{.thisclass}} {{{(\d+)}}}';
var html = '<h1 class="thisclass">Test</h1><h2 class="thisclass">Test2</h2> 1234 12';
var url = "http://perdu.com";
query = query.split(" ").map(o=>{
return o.replace(/\{\{\{(.*)\}\}\}/g, "$1");
}).map(o=>{
return o.replace(/\{\{(.*)\}\}/g, "$1");
});
var el = document.createElement( 'div' );
el.innerHTML = "<div class='outer'>"+html+"</div>";
var t1 = $("h1").text();
var t2 = $("h2").text();
var out = $(".outer").text();
var newArr = [];
newArr.push(query[0]+" "+query[1]+" "+url+" "+t1+t2+out);
newArr.push("{{{triple brackets = "+query[4]+"}}}");
newArr.push("{{double brackets = "+query[3]+"}}");
console.log(newArr);
newArr.map(o=>{
$("#res").append(o+"<br>");
});
Full example here: http://jsfiddle.net/k8em5twd/6/
So if this question is as simple as "why didn't the backslash show up in my output", then the answer is also very simple. Try escaping the backslash in your input string like so:
let output = parseEntry('static value %url% {{.thisclass}} {{{(\\d+)}}}', '<h1 class="thisclass">Test</h1><h2 class="thisclass">Test2</h2> 1234 12', "http://perdu.com");
The key is that {{{(\d+)}}} becomes {{{(\\d+)}}}. This way the slash is recognized as a character. Otherwise, \d is treated as an escape sequence. Output below.
function parseEntry(query, html, url) {
// logic draft :(
var re = new RegExp('{{{(.*)}}}');
regex = query.replace(re, "$1");
var newre = new RegExp(regex);
regged = html.replace(newre, "$1");
ret = query.replace(regex, regged);
// parse selectors
var re = new RegExp('{{(.*)}}');
newtext = html.replace(re, "$1");
ret = ret.replace(newtext, $(newtext).clone().html());
// parse %url%
ret = ret.replace("%url%", url);
// ret remaining
return ret;
}
// Called this way:
// THIS LINE IS CHANGED:
let output = parseEntry('static value %url% {{.thisclass}} {{{(\\d+)}}}', '<h1 class="thisclass">Test</h1><h2 class="thisclass">Test2</h2> 1234 12', "http://perdu.com");
console.log(output)
/**
should return:
static value http://perdu.com TestTest2 123412
{{{triple brackets = regex}}}
{{double brackets = jquery}}
**/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Ended up doing it myself, for the curious:
function parseEntry(query, url, ht) {
// parse regex expressions (triple brackets)
var re = new RegExp('{{{(.*)}}}', 'g');
q = query.match(re);
for (qq in q) {
var newregex = q[qq].replace("{{{", '').replace("}}}", '');
newregex = new RegExp(newregex, 'g');
newq = ht.match(newregex).join("");
query = query.replace(q[qq], newq);
}
// parse jquery expressions (double brackets)
re = new RegExp('{{(.*)}}', 'g');
q = query.match(re);
for (qq in q) {
var newjq = q[qq].replace("{{", '').replace("}}", '');
code = $('<div>'+ht+'</div>').find(newjq);
appendHTML = '';
code.each(function() {
appendHTML += $(this).html();
})
query = query.replace(q[qq], appendHTML);
}
// parse %url%
ret = query.replace("%url%", url);
// ret remaining
return ret;
}
let output = parseEntry('static value %url% {{.thisclass}} {{{(\\d+)}}}', "http://perdu.com", '<h1 class="thisclass">Test</h1><h2 class="thisclass">Test2</h2> 1234 12');
console.log(output);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I have encoded HTML entities, and I want to convert them to text.
This is the HTML encoded text:
دادن
And this is decoded text (Persian Language):
دادن
How can I convert the HTML encoded text to the decoded text using JavaScript?
Try this:
function htmlToText(html) {
var el = document.createElement('div');
el.innerHTML = html;
return el.textContent;
}
var text = htmlToText('دادن');
console.log(text);
This code takes the HTML entities and converts them into text.
If you want to use a pure JavaScript solution (no DOM/JQuery) you can do
var decodeHtmlEntities = function(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
return String.fromCharCode(dec);
});
};
var encodeHtmlEntities = function(str) {
var buf = [];
for (var i = str.length - 1; i >= 0; i--) {
buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
}
return buf.join('');
};
console.log(decodeHtmlEntities("دادن"))
console.log(encodeHtmlEntities("دادن"))
Is there a clever way to figure out all attributes of an object referenced within a function WITHOUT executing it?
For example let's say I have the following function:
var fun = function(a){
a.text = "hello world";
a.title = "greetings";
a.ran = "fun";
}
I would like some magical function that does:
var results = magical_function(fun, {});
// results = ["text", "title", "ran"];
Basically it's returning all attributes of the argument object that will be accessed inside the fun function, WITHOUT having to actually execute fun.
I said "without running" it because I don't want the act of checking this affect any outside app logic, but I am fine as long as the checking doesn't influence the outside world.
function.toString() is going to return a parsable string. Use Regex on that.
var fun = function(a){
a.text = "hello world";
a.title = "greetings";
a.ran = "fun";
}
var fun2 = function(x){
x.text = "hello world";
x.title = "greetings";
a.ran = "fun";
}
function magical_function(func) {
var data = func.toString();
var r = /a\.([a-z]+)/g;
var matches = [];
var match;
while ((match = r.exec(data)) != null) {
matches.push(match[1]);
}
return matches;
}
function magical_function_2(func) {
var data = func.toString();
var attribute_finder_r = new RegExp('function \\(([a-z]+)\\)');
var attribute_name_match = attribute_finder_r.exec(data);
if (!attribute_name_match) {
throw 'Could not match attribute name';
}
var attribute_name = attribute_name_match[1];
var r = new RegExp(attribute_name + '.([a-z]+)', 'g');
var matches = [];
var match;
while ((match = r.exec(data)) != null) {
matches.push(match[1]);
}
return matches;
}
console.log(magical_function(fun));
console.log(magical_function_2(fun2));
var myObj = {
text: '',
title: '',
ran: ''
}
var fun = function(a){
a.text = "hello world";
a.title = "greetings";
a.ran = "fun";
}
function magical_function(func, obj) {
var data = func.toString();
var keys = Object.keys(obj);
var regExp = '';
for (let i= 0; i < keys.length; i++) {
if (keys.length > 1 && ((i+1) < keys.length)) {
regExp += keys[i] + '|';
}
else if (keys.length == 1 || ((i+1) == keys.length)) {
regExp += keys[i];
}
}
regExp = '\.(['+ regExp +']+)\\s*=';
var r = new RegExp(regExp, 'g');
var matches = [];
var match;
while ((match = r.exec(data)) != null) {
if (Object.keys(obj).includes(match[1]))
matches.push(match[1]);
}
return matches;
}
console.log(magical_function(fun, myObj));
There's no way those attributes are going to get set before running the function.
The only thing you can do is to write another version of the function which only accesses the object passed and returns the result.
I am attempting to do a quick replace of the 'innerHTML' of the 'code' element. I thought this may work:
function codeDisplay ( ) {
var code = document.getElementsByTagName('code').innerHTML;
var codeExam1 = new RegExp('<', 'gm');
var codeExam2 = new RegExp('>', 'gm');
code.replace(codeExam1, '<');
code.replace(codeExam2, '>');
}
Do I need to perform any additional steps to push the information back to the browser or conversion of data types maybe? Or am I completely wrong in how 'RegEx' and 'innerHTML' work? I appreciate the feedback in advance.
So, first fo all:
var code = document.getElementsByTagName('code').innerHTML;
document.getElementsByTagName returns a list of elements not just one. So, if your purpose is escaping all the code tags you have in the page, you need to iterate them.
Second, I believe you can avoid regexp just using textContent (where supported) or innerText.
var codes = document.getElementsByTagName("code");
for (var i = 0, code; code = codes[i++];) {
if ("textContent" in code)
code.textContent = code.innerHTML;
else if ("innerText" in code)
code.innerText = code.innerHTML;
}
or create a new text node:
var codes = document.getElementsByTagName("code");
for (var i = 0, code, html; code = codes[i++];) {
html = code.innerHTML;
code.innerHTML = "";
code.appendChild(document.createTextNode(html));
}
That's should escape every html entities. If you still want to use the regexp, maybe as fallback, you can have this kind of function:
var escapeEntities = (function(){
var entities = {"<" : "lt", ">" : "gt", "&" : "amp" };
var re = new RegExp("[" + Object.keys(entities).join("") + "]", "g");
function replaceEntities(match) {
return match in entities ? "&" + entities[match] + ";" : match;
}
return function(value) {
return value.replace(re, replaceEntities);
}
})()
And then in your code:
code.innerHTML = escapeEntities(code.innerHTML);
Note that if Object.keys is not supported you can easily use a shims (as indicated in the link); or simply replace manually the list of entities you support:
var entities = {"<" : "lt", ">" : "gt", "&" : "amp" };
var re = /[<>&]/g;
In that case you need to remember to add in both entities and re variables a new entity you want to support in the future; Object.keys just help you in maintenance.
Use assignment:
code = code.replace(codeExam1, '<');
code = code.replace(codeExam2, '>');
And modify your code like this:
function codeDisplay ( ) {
var codeArray = document.getElementsByTagName('code');
var codeExam1 = new RegExp('<', 'gm');
var codeExam2 = new RegExp('>', 'gm');
for ( var i = 0 ; i < codeArray.length ; ++i ){
var code = codeArray[i].innerHTML;
code.replace(codeExam1, '<');
code.replace(codeExam2, '>');
codeArray[i].innerHTML = code;
}
}
Replace returns a new string containing the result. See MDN for example.
To actually replace the contents of code you code has to look like this:
function codeDisplay ( ) {
var code = document.getElementsByTagName('code').innerHTML;
var codeExam1 = new RegExp('<', 'gm');
var codeExam2 = new RegExp('>', 'gm');
code = code.replace( codeExam1, '<');
code = code.replace(codeExam2, '>');
document.getElementsByTagName('code').innerHTML = code;
}
Or a shorter version (could be even shorter, but in my opinion just at the cost of readability):
function codeDisplay ( ) {
var code = document.getElementsByTagName('code').innerHTML;
code = code.replace( /</gm , '<' )
.replace( />/gm, '>' );
document.getElementsByTagName('code').innerHTML = code;
}
Try this:
function codeDisplay ( ) {
var s = document.getElementsByTagName('code').innerHTML;
s = s.replace(/\</g,'<');
s = s.replace(/\>/g,'>');
document.getElementsByTagName('code').innerHTML = s;
}
i want to strip just text values from below html with js.
var Str = "<span style="">MY name is KERBEROS.</span><B>HELLO Everbody</B>"
All text strips with codes that is below;
[^<>]+(?=[<])
But i want to strip just UPPERCASE words. Clresult must be: MY, KERBEROS, HELLO
Thank you already now for your suggestions.
Regards,
Kerberos
Here is your code, gives output: MY,KERBEROS,HELLO
<script>
String.prototype.stripHTML = function()
{
var matchTag = /<(?:.|\s)*?>/g;
return this.replace(matchTag, "");
};
String.prototype.getUpperCaseWords = function()
{
var matchTag1 = /\b([A-Z])+\b/g;
var o = this.match(matchTag1);
return o;
};
var Str = "<span style=''>MY name is KERBEROS.</span><B>HELLO Everbody</B>";
var out1 = Str.stripHTML();
var out2 = out1.getUpperCaseWords();
alert(out2);
</script>
This is another solution in JavaScript using just one line of regex:
String.prototype.stripHTML = function()
{
var matchTag = /<(?:.|\s)*?>/g;
return this.replace(matchTag, "").match(/\b([A-Z])+\b/g);
};
var Str = "<span style=''>MY name is SATYA PRAKASH.</span><B>HELLO Everyone</B>";
var out1 = Str.stripHTML();