using multiple .replace calls on an array of variables in Javascript / jQuery - javascript

I am working on a tool that would receive text that has been copied from a word document, and return an html output for copy/paste into an email client for email marketing.
During this process, one of the steps the tool needs to handle is the replacement of special characters within the copied values. The output needs to show the encoded values so when they are copied into the email client, they render accordingly during the mail send process
The problem is that there are multiple inputs the user can populate and right now the code is VERY WET... I want to set up the tool to be a little cleaner, and not repeat the code as often.
Currently the input is given to the tool via a prompt();
I am taking that input and replacing the special characters ™, ®, Ø, ´, ”, ‟ and others (partial list given for this example) as needed:
JS (Commented Version)
msg2 = prompt("enter text here");
//long version to tag each replacement with it's identifying name
msg2 = msg2.replace(/[\u0027]/g, '''); // Apostrophe ´
msg2 = msg2.replace(/[\u2122]/g, '™'); // trademark ™
msg2 = msg2.replace(/[\u00AE]/g, '®'); // R-Ball ®
msg2 = msg2.replace(/[\u201c]/g, '"'); // Left Double Quote ‟
msg2 = msg2.replace(/[\u201D]/g, '"'); // Right Double Quote ”
msg2 = msg2.replace(/[\u2018]/g, '''); // Left Single Quote ‛
msg2 = msg2.replace(/[\u2019]/g, '''); // Right Single Quote ’
msg2 = msg2.replace(/[\u2022]/g, 'ߦ') // Bullet •
JS (Short Version)
msg2 = prompt("enter text here");
msg2 = msg2.replace(/[\u0027]/g, ''').replace(/[\u2122]/g,
'™').replace(/[\u00AE]/g, '®').replace(/[\u201c]/g,
'"').replace(/[\u201D]/g, '"').replace(/[\u2018]/g,
''').replace(/[\u2019]/g, ''').replace(/[\u2022]/g,
'ߦ');
BUT... I need to run this same replacement on a number of prompts. I don't want to repeat this in the code a bunch of times with each of the variables changing as needed.
What I would rather do is create a function to handle the replacement, and then simply create an array of the variables and run the function on the array...
Example
function txtEncode () {
...replacment code here...
}
var inputTxt = [msg1, msg2, msg3...];
for (var i=0; i < inputTxt.length; i++){
txtEncode(i)
}

Just make an array with replacement pairs:
var replacements = [ ["&", "&"], ["'", """] etc
and apply them one by one:
replacements.forEach(function(pair) {
msg = msg.split(pair[0]).join(pair[1]);
});
split/join is better to replace literal strings than .replace which is intended for use with regular expressions.
Also, your encoding doesn't look right, &#174; will be displayed as ®, not as ®

You can use a global find/replace function and extend the string prototype, I have this code in one of my fiddles, but I can't find the origin.
Code:
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
var regex;
for (var i = 0; i < find.length; i++) {
regex = new RegExp(find[i], "g");
replaceString = replaceString.replace(regex, replace[i]);
}
return replaceString;
};
var msg2 = 'demo \u0027'
var find = ["\u0027"];
var replace = ["&#39;"];
msg2 = msg2.replaceArray(find, replace);
Demo: http://jsfiddle.net/IrvinDominin/YQKwN/

Add a method to the String object for your code.
String.prototype.myCleanString = function(){
return this.replace(/[\u0027]/g, '&#39;')
.replace(/[\u2122]/g,'&#153;')
.replace(/[\u00AE]/g, '&#174;')
.replace(/[\u201c]/g, '&#34;')
.replace(/[\u201D]/g, '&#34;')
.replace(/[\u2018]/g, '&#39;')
.replace(/[\u2019]/g, '&#39;')
.replace(/[\u2022]/g, '&#2022;')
.replace(/foo/g, 'bar');
}
Call as needed... http://jsfiddle.net/XKHNt/

Related

How to define a line break in extendscript for Adobe Indesign

I am using extendscript to build some invoices from downloaded plaintext emails (.txt)
At points in the file there are lines of text that look like "Order Number: 123456" and then the line ends. I have a script made from parts I found on this site that finds the end of "Order Number:" in order to get a starting position of a substring. I want to use where the return key was hit to go to the next line as the second index number to finish the substring. To do this, I have another piece of script from the helpful people of this site that makes an array out of the indexes of every instance of a character. I will then use whichever array object is a higher number than the first number for the substring.
It's a bit convoluted, but I'm not great with Javascript yet, and if there is an easier way, I don't know it.
What is the character I need to use to emulate a return key in a txt file in javascript for extendscript for indesign?
Thank you.
I have tried things like \n and \r\n and ^p both with and without quotes around them but none of those seem to show up in the array when I try them.
//Load Email as String
var b = new File("~/Desktop/Test/email.txt");
b.open('r');
var str = "";
while (!b.eof)
str += b.readln();
b.close();
var orderNumberLocation = str.search("Order Number: ") + 14;
var orderNumber = str.substring(orderNumberLocation, ARRAY NUMBER GOES HERE)
var loc = orderNumberLocation.lineNumber
function indexes(source, find) {
var result = [];
for (i = 0; i < source.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
alert(result)
}
indexes(str, NEW PARAGRAPH CHARACTER GOES HERE)
I want all my line breaks to show up as an array of indexes in the variable "result".
Edit: My method of importing stripped all line breaks from the document. Using the code below instead works better. Now \n works.
var file = File("~/Desktop/Test/email.txt", "utf-8");
file.open("r");
var str = file.read();
file.close();
You need to use Regular Expressions. Depending on the fields do you need to search, you'l need to tweek the regular expressions, but I can give you a point. If the fields on the email are separated by new lines, something like that will work:
var str; //your string
var fields = {}
var lookFor = /(Order Number:|Adress:).*?\n/g;
str.replace(lookFor, function(match){
var order = match.split(':');
var field = order[0].replace(/\s/g, '');//remove all spaces
var value = order[1];
fields[field]= value;
})
With (Order Number:|Adress:) you are looking for the fields, you can add more fields separated the by the or character | ,inside the parenthessis. The .*?\n operators matches any character till the first break line appears. The g flag indicates that you want to look for all matches. Then you call str.replace, beacause it allows you to perfom a single task on each match. So, if the separator of the field and the value is a colon ':', then you split the match into an array of two values: ['Order number', 12345], and then, store that matches into an object. That code wil produce:
fields = {
OrderNumber: 12345,
Adresss: "my fake adress 000"
}
Please try \n and \r
Example: indexes(str, "\r");
If i've understood well, wat you need is to str.split():
function indexes(source, find) {
var order;
var result = [];
var orders = source.split('\n'); //returns an array of strings: ["order: 12345", "order:54321", ...]
for (var i = 0, l = orders.length; i < l; i++)
{
order = orders[i];
if (order.match(/find/) != null){
result.push(i)
}
}
return result;
}

Javascript get all text in between string

I have string content that gets delivered to me via TCP. This info is only relevant because it means that I do not consistently retrieve the same string. I have a <start> and <stop> separator to ensure that any time I get the data via TCP, I am outputting the full content.
My incoming content looks like so:
<start>Apple Bandana Cadillac<stop>
I want to get everything in between <start> and <stop>. So just Apple Bandana Cadillac.
My script to do this looks like so:
servercsv.on("connection", function(socket){
let d_basic = "";
socket.on('data', function(data){
d_basic += data.toString();
let d_csvindex = d_basic.indexOf('<stop>');
while (d_csvindex > -1){
try {
let strang = d_basic.substring(0, d_csvindex);
let dyson = strang.replace(/<start>/g, '');
let dson = papaparse.parse(dyson);
myfunction(dson);
}
catch(e){ console.log(e); }
d_basic = d_basic.substring(d_csvindex+1);
d_csvindex = d_basic.indexOf('<stop>');
}
});
});
What this means is that I am getting everything before the <stop> string and outputting it. I have also included the line let dyson = strang.replace(/<start>/g, ''); because I want to remove the <start> text.
However, because this is TCP, I am not guranteed to get all parts of this string. As a result, I frequently get back stop>Apple Bandana Cadillac<stop> or some variation of this (such as start>Apple Bandana Cadillac<stop>. It is not consistent enough that I can just do strang.replace("start>", "")
Ideally, I would like my separator to select content that is in between <start> and <stop>. Not just <stop>. However, I am unsure how to do so.
Alternatively, I can also settle for a regex that retrieves all combination of <start><stop> strings during my while loop, and just delete them. So check for <, s, t, a, r, t individually and so forth. But unsure how to implement regex to delete portions of a whole string.
Assuming you get full response:
var test = "<start>Apple Bandana Cadillac<stop>";
var testRE = test.match("<start>(.*)<stop>");
testRE[1] //"Apple Bandana Cadillac"
If there are new lines between <start> and <stop>
var test = "<start>Apple Bandana Cadillac<stop>";
var testRE = test.match("<start>([\\S\\s]*)<stop>");
testRE[1] //"Apple Bandana Cadillac"
Using regular expressions capturing group here.
Try this regex with replace() method:
/<st.*?>(.*?)(?!<st)/g
Literal.................................................: <st
Any char zero or more times lazily...: .*?
Literal..................................................: >
Begin capture group..........................: (
Any char zero or more times lazily...: .*?
End capture group.............................: )
Begin negative lookahead.................: (?!
Literal...................................................: <st
End negative lookahead....................: )
In the Demo below notice that the test example consists of multiple lines, and variances of <start> and <stop> (basically <st).
Demo 1
var rgx = /<st.*?>(.*?)(?!<st)/g;
var str = `<start>Apple Bandana Cadillac<stop>
<stop>Grapes Trampoline Ham<stop>
<start>Kebab Matador Pencil<start>`;
var res = str.replace(rgx, `$1`);
console.log(res);
Update
"say I have op>Grapes Trampoline Ham<stop>...still trying to remove all parts of the string <stop>"
/^(.*?>)(.*?)(<.*?)$/gm;
A simple explanation will have to do since a step-by-step such as Demo 1 would take too much time.
This RegEx is multiline. /m
^..........Begin line.
(.*?>)..Lazily capture everything until literal >........[Return as $1]
(.*?)...Then lazily capture everything until................[Return as $2]
(<.*?)..Literal < and lazily capture everything until..[Return as $3]
$...........End line.
The trick is to replace the second capture $2 and leave $1 and $3 alone.
Demo 2
var rgx = /^(.*?>)(.*?)(<.*?)$/gm;
var str = `<start>Apple Bandana Cadillac<stop>
<stop>Grapes Trampoline Ham<stop>
<start>Kebab Matador Pencil<start>
op>Score False Razor<stop>
`;
var res = str.replace(rgx, `$2`);
console.log(res);

Javascript string replace() method malfunctioning for dots and commas

I want to replace a text by using the user input values but for the below script dots and commas are malfunctioning when replacing. I tried (/\x/) method but it's not working, maybe because it's a value. So, how can I execute output more accurately?
function myFunction() {
var str = document.getElementById("text").value;
var x = new RegExp(document.getElementById("x").value, "g");
var y = document.getElementById("y").value;
var txt = str.replace(x, y);
document.getElementById("newText").innerHTML = txt;
}
function reset() {
document.getElementById("text").value = "";
}
example:
text = ..........a.a.a..a..a..aaaaaa..a.a.
x = ..a
y = B
output = ........B.BBBBBaaB.a.
but output should be
........B.a.aBBBaaaaaB.a.
(Sorry for the unprofessional example...)
I am just now learning JS and not a professional and I'm trying to make a replacer web page using JS like in MS Notepad where you can press ctrl+H and replace any word or letter.
You're looking for RegExp.escape, unlucky for you - the smart people at the JavaScript technical committee decided to postpone its inclusion in the standard because of an edge case you, or anyone else will likely never run into.
if(!RegExp.escape){
RegExp.escape = function(s){
return String(s).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
};
}
Then, you can call it on a value and it'll escape it for use in new RegExp:
var raw = document.getElementById("x").value;
var x = new RegExp(RegExp.escape(raw), "g");
You want this regex - [.]{2}[a] or [.][.][a].
Two dots mandatory with trailing a. And it should be of 3 characters.

Extract links in a string and return an array of objects

I receive a string from a server and this string contains text and links (mainly starting with http://, https:// and www., very rarely different but if they are different they don't matter).
Example:
"simple text simple text simple text domain.ext/subdir again text text text youbank.com/transfertomealltheirmoney/witharegex text text text and again text"
I need a JS function that does the following:
- finds all the links (no matter if there are duplicates);
- returns an array of objects, each representing a link, together with keys that return where the link starts in the text and where it ends, something like:
[{link:"http://www.dom.ext/dir",startsAt:25,endsAt:47},
{link:"https://www.dom2.ext/dir/subdir",startsAt:57,endsAt:88},
{link:"www.dom.ext/dir",startsAt:176,endsAt:192}]
Is this possible? How?
EDIT: #Touffy: I tried this but I could not get how long is any string, only the starting index. Moreover, this does not detect www: var str = string with many links (SO does not let me post them)"
var regex =/(\b(https?|ftp|file|www):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig; var result, indices = [];
while ( (result = regex.exec(str)) ) {
indices.push({startsAt:result.index});
}; console.log(indices[0].link);console.log(indices[1].link);
One way to approach this would be with the use of regular expressions. Assuming whatever input, you can do something like
var expression = /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/gi;
var matches = input.match(expression);
Then, you can iterate through the matches to discover there starting and ending points with the use of indexOf
for(match in matches)
{
var result = {};
result['link'] = matches[match];
result['startsAt'] = input.indexOf(matches[match]);
result['endsAt'] =
input.indexOf(matches[match]) + matches[match].length;
}
Of course, you may have to tinker with the regular expression itself to suit your specific needs.
You can see the results logged by console in this fiddle
const getLinksPool = (links) => {
//you can replace the https with any links like http or www
const linksplit = links.replace(/https:/g, " https:");
let linksarray = linksplit.split(" ");
let linkspools = linksarray.filter((array) => {
return array !== "";
});
return linkspools;
};

replace() with RegExp on array elements

I want to write a JavaScript function which converts some simple BBcode Tags like [red] [/red] to Html-Tags. I think the replace() function is the best way to do it. I wrote a simple testfunction to try it, but it does not seem to work.
/**
* #function
* #description Replaces the bb-tags with html-tags
*/
function bbToHtml(form) {
debugger
var text = form.text.value;
bbTags = new Array("[red]", "[yellow]", "[green]", "[/red]", "[/yellow]", "[/green]");
htmlTags = new Array("<font color='red'>", "<font color='yellow'>", "<font color='green'>", "</font>", "<font>", "</font>");
for (var i = 0; i < bbTags.length; i++) {
var re = new RegExp(bbTags[i], "g");
text = text.replace(re, htmlTags[i]);
}
alert(text);
}
It should convert "[red]hello[/red]" to "<font color='red'>hello</font>", but it just gives me a weird string.
What is wrong? I think this has something to do with my regular expression.
[ and ] have special meaning in regular expressions and need to be escaped, moreover you do not need regular expressions the way you've written your code and can just do:
function bbToHtml(form) {
debugger
var text = form.text.value;
bbTags = new Array("[red]", "[yellow]", "[green]", "[/red]", "[/yellow]", "[/green]");
htmlTags = new Array("<font color='red'>", "<font color='yellow'>", "<font color='green'>", "</font>", "<font>", "</font>");
for (var i = 0; i < bbTags.length; i++) {
while(text.indexOf(bbTags[i])!==-1){
text = text.replace(bbTags[i], htmlTags[i]);
}
}
alert(text);
}
Just to let you know, you can use array literals so instead of arrays. new Array(comma seperated values) is identical to [comma seperated values] in javascript.
Also, you can use your array like a map in your case, for example:
var bbTagsToHTML = {}
bbTagsToHtml["[red]"] = "<font color='red'>"
and iterate through that.
If you would like you can escape your regular expressions too, please see How do you use a variable in a regular expression? for a function that does that.
You can also do that manually. "[red]" becomes "\[red\]" (the bracket escaped).
just change this line
text = text.replace(re, htmlTags[i]);
into
text = text.replace(bbTags[i], htmlTags[i]);
removing unuseful code.
replace works also on 'normal' (not regex) values as argument.
If you want to do it with regex you can simplify a lot. No arrays or loops:
var str = '[red]foo[/red] hello world [blue]hey[/blue]',
re = /\[(\w+)\](.*)\[\/\1\]/g;
str = str.replace(re, '<font color="$1">$2</font>');
console.log(str);
//^ <font color="red">foo</font> hello world <font color="blue">hey</font>
Also, as a side note, font is rarely used anymore I'd suggest you use a span with a class.

Categories

Resources