Optimize code for profanity filter - javascript

I have a chat app and I want to use a profanity filter.
I've came up with: http://jsfiddle.net/691nruoL/4/
var chatMessage = "sex it up what the fuck tits lol fuck titsss";
// Potentially an array of hundreds of words coming from a JSON file
var badWords = ['sex', 'fUck', 'dick', 'penis', 'cum', 'tits', 'fuck'];
for (var i = 0; i < badWords.length; i++) {
if (chatMessage.indexOf(badWords[i].toLowerCase()) !== -1) {
chatMessage = chatMessage.replace(badWords[i].toLowerCase(), pushAsterisksForWordLength(badWords[i].length));
}
}
function pushAsterisksForWordLength(asterisksLength) {
var censoredWordArray = [];
for (var i = 0; i < asterisksLength; i++) {
censoredWordArray.push('*');
}
return censoredWordArray.join('');
}
console.log(chatMessage);
How would you optimize it? I feel like with many bad words in the array, it could be quite slow.

Use regexp:
var chatMessage = "sex it up what the fuck tits lol fuck titsss";
var badWords = ['sex', 'fUck', 'dick', 'penis', 'cum', 'tits', 'fuck'];
var regExpSource = badWords.join('|');
var regExpFilter = new RegExp(regExpSource, 'ig');
console.log(regExpFilter.test(chatMessage));
And remove words with asterisks like with:
chatMessage.replace(regExpFilter, function () {
return '****';//Don't matter what that was a word
});

// Prepare for search (just once)
var badWordsRE = new RegExp(badWords.join('|'), "gi");
var asterisks = "";
badWords.forEach(function(word) {
while (word.length > asterisks.length) asterisks += "*";
});
// Search and destroy
chatMessage.replace(badWordsRE, function(word) {
return asterisks.substring(0, word.length);
});
// => "*** it up what the **** **** lol **** ****ss"

Subsitiutes each letter in a "bad" word with an asterisk without looping over the word:
chatMessage.replace(/sex|fuck|tits/gi,function( word ){
return word.replace(/./g,'*')
});
http://jsfiddle.net/691nruoL/5/

Related

javascript- replace text with part of the file name

I'm trying to create a script in adobe illustrator that will check if a file name contains "ph" +5 numbers.
If it has been found then it will replace a part of a text with the match from the file name.
This is what I have so far I just can't get it to work, the text is replaced with "null"
var doc = app.activeDocument;
var name = doc.name;
var match = name.match(/ph\d{5}/);
for (i = 0; i < doc.textFrames.length; i++)
{
doc.textFrames[i].contents = doc.textFrames[i].contents.replace(/ph00000/gi, match);
}
I'd try this:
var doc = app.activeDocument;
var match = doc.name.match(/ph\d{5}/);
if (match != null) {
for (i = 0; i < doc.textFrames.length; i++) {
doc.textFrames[i].contents = doc.textFrames[i].contents.replace(/ph00000/gi, match[0]);
}
}
You can encapsulate the text that you want to replace with group constructs, and since you're using String.prototype.replace, you can capture the parenthesized group and pass the callback function as the 2nd argument in your .replace function.
Read more about it here
Example:
const textString = "This is ph54321 or ph12345";
const newString1 = textString.replace(/(ph)\d{5}/gi, function (matches, p1) {
return p1 + "appended"; // "This is phappended or phappended"
});
const newString2 = textString.replace(/ph(\d{5})/gi, function (matches, p1) {
return "BIGPH" + p1; // "This is BIGPH54321 or BIGPH12345"
});
console.log({newString1});
console.log({newString2});

Highlight words from string started with #

There is a string that may contain nicknames given by #nickname. Nickname can be inputed by user with typo by concatenation with previous word, like
Hello my inst is#nickname
Also nickname word can be situated at the beginning of the new paragraph, hence just using split(' ') wouldn’t work.
What I want ultimately do is to after user inputs, highlight nicknames in string by covering them with <span> setting some styles and adding onclick link to instagram with that account.
Solution I’ve made so far:
<script>
window.onload=function()
{
var text = "Hello #buf world #text";
text = Synt(text);
var a = addP(document.body,text,30,30,"black",20);
a.innerHTML=text;
}
function Synt(a)
{
if(a.search('#')==-1)
return a;
else
{
var regex = /#/gi, result, indices = [];
while ( (result = regex.exec(a)) ) {
indices.push(result.index);
}
var a1 = (' ' + a).slice(1);
var ar = a.split('');
for(var i=0;i<indices.length;i++)
{
var r=[];
var rr=0;
for(var j=indices[i];j<a.length&&(isLetter(a[j])||a[j]=='.'||a[j]=='_'||rr==0);rr++,j++)
r[rr]=a[j];
r=r.join('');
a1 = a1.replace(r,'<span style="color:blue">'+r+'</span>');
}
return a1;
}
}
function isLetter(str) {
return str.length === 1 && str.match(/[a-z|0-9]/i);
}
function addP(par,text,left,top,color='black',size='17px', fun=0)
{
var p = document.createElement('p');
p.style.position = 'absolute';
p.style.color=color
p.style.fontSize=size;
p.style.fontFamily='Arial';
par.appendChild(p);
p.style.left=left;
p.style.top=top;
p.innerText=text;
if(fun)
p.onclick=fun;
return p;
}
</script>

How can I get the text to which a Nested Style is applied in InDesign

I am trying to write a script that will convert all characters to lowercase if a particular nested style is applied. I can't seem to figure out the correct syntax to get the text.
I originally tried the following, which worked to an extend, but lowercased the entire paragraph rather than only the text that has the character style applied:
function lowerCaseNest(myPStyle, myCStyle){
var myDocument = app.documents.item(0);
//Clear the find/change preferences.
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
//Set the find options.
app.findChangeTextOptions.caseSensitive = false;
app.findChangeTextOptions.includeFootnotes = false;
app.findChangeTextOptions.includeHiddenLayers = false;
app.findChangeTextOptions.includeLockedLayersForFind = false;
app.findChangeTextOptions.includeLockedStoriesForFind = false;
app.findChangeTextOptions.includeMasterPages = false;
app.findChangeTextOptions.wholeWord = false;
app.findTextPreferences.appliedParagraphStyle = myPStyle;
var missingFind = app.activeDocument.findText();
var myDoc = app.documents[0];
for ( var listIndex = 0 ; listIndex < missingFind.length; listIndex++ ) {
for (i = missingFind[listIndex].nestedStyles.length-1;i>=0; i--) {
for (j = missingFind[listIndex].nestedStyles[i].parent.characters.length-1;j>=0; j--) {
if (missingFind[listIndex].nestedStyles[i].parent.characters[j].contents.appliedCharacterStyle(myCStyle)) {
var myString = missingFind[listIndex].nestedStyles[i].parent.characters[j].contents;
if (typeof(myString) == "string"){
var myNewString = myString.toLowerCase();
missingFind[listIndex].nestedStyles[i].parent.characters[j].contents = myNewString;
}
}
}
}
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
}
I then tried playing around with appliedNestedStyles, but can't seem to figure out how to retrieve the text that the nested style is applied to.
Could anyone help with this?
Thanks!
John
Unless I am wrong the appliedNestedStyle can be looked after in the F/C dialog by targeting the applied characterStyle:
GREP
Find : .+
Format : character style => myCharStyle
then
var found = doc.findGrep();
…
I actually took a different tack, and figured out something that works:
function lowerCaseNest(myPStyle, myCStyle){
for (var i = 0; i < app.activeDocument.stories.length; i++){
for (var j = 0; j < app.activeDocument.stories[i].paragraphs.length; j++){
var myP = app.activeDocument.stories[i].paragraphs[j];
if (myP.appliedParagraphStyle.name==myPStyle) {
for (k=0; k<myP.characters.length; k++) {
if(typeof(myP.characters[k].appliedNestedStyles[0]) != 'undefined'){
if(myP.characters[k].appliedNestedStyles[0].name == myCStyle) {
var myC = myP.characters[k].contents;
if (typeof(myC)=='string'){
var myNewString = myC.toLowerCase();
myP.characters[k].contents = myNewString;
}
}
}
}
}
}
}
}
Still would be interested in knowing if there's an easier way to handle this, as I'm afraid this may take longer to run on long documents, since it's dealing with every paragraph individually.

Javascript missing ) after arguments list

A JavaScript function that takes a string argument and counts its properties.
I'm not sure why it's not working I think there is some problem with the console.log line.
function superCounter (TheWord) {
var NOWords = TheWord.split('').length;
var NOLetters = TheWord.length;
var NOSpaces = 0;
for (var i = 0; i < superCounter.length; i++)
if (TheWord[i] === " ") {
NOSpaces = +1;
}
var CTCharacters = TheWord.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
var TNCharacters = CTCharacters.length;
var AWLength = NOLetters / NOWords;
console.log("words:"
NOWords, "letters:"
NOLetters, "spaces:"
NOSpaces, "chars:"
TNCharacters, "avgLength:"
AWLength)
}
superCounter("The grintch made it happen");
Your console.log statement is wrong this is the write one.
You have missed commas after every argument. console.log arguments should be separated by ,.
// console.log("words:" NOWords, "letters:" NOLetters, "spaces:" NOSpaces, "chars:" TNCharacters, "avgLength:" AWLength)
console.log("words:", NOWords, "letters:", NOSpaces, "chars:", TNCharacters, "avgLength:", AWLength);

pushing into arrays in javascript

My script (is meant to) grab text from the a page (which works fine) and then splits it by by newline (\n) and puts each splitted string into an array called "dnaSequence"; from there it loops through each element in the array and if the string contains the character ">" it assigns that string to the "var header_name", else it pushes all other lines into a new array called "dnaSubseq". The original text looks something like this:
>header_1
gctagctagc
cgcgagcgagc
>header_2
gcgcatgcgac
When I execute the code it fails to alert on anything. Here is the code:
function loaderMy() {
var dnaSubseq = [];
var dnaSequence = [];
var header_name = "";
var splittedLines = document.getElementById("page-wrapper").innerText;
dnaSequence = splittedLines.split('\n');
for (var i = 0; i < dnaSequence.length; i++) {
if (dnaSequence[i].match(/>/)) {
header_name = dnaSequence[i];
alert(header_name);
}
else {
dnaSubseq.pushValues(dnaSequence[i]);
}
alert(dnaSubseq);
}
}
Change
dnaSubseq.pushValues(dnaSequence[i]);
To
dnaSubseq.push(dnaSequence[i]);
If it doesn't alert anything, that means you forgot to invoke the function :)
loaderMy();
http://jsfiddle.net/zszyg5qx/
Try this function
function loaderMy() {
var dnaSubseq = [];
var dnaSequence = [];
var header_name = "";
var splittedLines = document.getElementById("page-wrapper").innerText;
dnaSequence = splittedLines.split('\n');
for (var i = 0; i < dnaSequence.length; i++) {
if (dnaSequence[i].match(/>/)) {
header_name = dnaSequence[i];
alert(header_name);
}
else {
dnaSubseq.push(dnaSequence[i]);
}
alert(dnaSubseq);
}
}

Categories

Resources