.replace() only replaces one instance - replace

I'm trying to make a text that censors bad words if its in the input. Here's my code:
var NotAllowed [
'test'
]
var sendmessage = 'test this is a test to see if it censors this test'
for (i = 0; i < NotAllowed.length; i++){
sendmessage = sendmessage.replace(NotAllowed[i], '######')
}
console.log(sendmessage)
The output looks something like "###### this is a test to see if it censors this test". I know about the "/g" thing but I don't know how to implement it in this case.

You can use RegExp object it is used for matching text with a pattern.
var NotAllowed =[
'test'
]
var sendmessage = 'test this is a test to see if it censors this test'
for (i = 0; i < NotAllowed.length; i++){
sendmessage = sendmessage.replace(new RegExp(NotAllowed[i], "g"), '######')
}
console.log(sendmessage)

Related

Extracting a string from gmail subject line

I am new to both writing RegEx as well as Google Apps Script, and am cutting my teeth on a simple problem, extracting a specific string within an email subject line in emails with X label into a Google Sheet. I've found some info on how to get this done, but I'm not getting anything output into my sheet. The syntax of the string I'm trying to extract is (1 or 4)(A or P)(0-9)(four more alphanumeric characters). So a few examples would be 1A8D3KK, 4P3A4EE, and 1A5T4EE.
Here's what I've got:
function getEWO() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("DamageClaims");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages()[0];
for (var j=0; j<messages.length; j++)
{
var date = messages.getDate();
var sub = messages[j].getSubject();
var getEWOstring = new RegExp ("(1|4)(A|P)[0-9]\w{4}");
console.log(getEWOstring);
let ewo = getEWOstring.exec(sub)
SpreadsheetApp.getActiveSheet().appendRow([ewo])
var debugmessage = ("EWO " + ewo + " has been added")
SpreadsheetApp.getActive().toast(debugmessage);
}
It's not outputting anything into my sheet, nor is it displaying my little debugger message.
This works for me:
/(1|4)(A|P)\d[A-Z0-9]{4}/g

How do I outdent by a specific amount of tabs?

I'm trying to create a function that I can use to outdent (versus indent) a specific amount.
Here is what I have so far. This removes all tabs at the beginning of the lines. I think I need to create a dynamic pattern or use a function but I'm stuck:
var outdentPattern:RegExp = /([\t ]*)(.+)$/gm;
function outdent(input:String, outdentAmount:String = "\t"):String {
var outdentedText:String = input.replace(outdentPattern, outdentAmount + "$2");
return outdentedText;
}
Here is test data:
<s:BorderContainer>
<html:htmlOverride><![CDATA[
<script>
var test:Boolean = true;
test = "string";
</script>]]>
</html:htmlOverride>
</s:BorderContainer>
The test would be remove one tab, remove two tabs, etc.
Expected results at one tab would be:
<s:BorderContainer>
<html:htmlOverride><![CDATA[
<script>
var test:Boolean = true;
test = "string";
</script>]]>
</html:htmlOverride>
</s:BorderContainer>
And two tabs:
<s:BorderContainer>
<html:htmlOverride><![CDATA[
<script>
var test:Boolean = true;
test = "string";
</script>]]>
</html:htmlOverride>
</s:BorderContainer>
And three tabs with the inner tabs (whitespace) collapsing down:
<s:BorderContainer x="110" height="160" width="240" y="52">
<html:htmlOverride><![CDATA[
<script>
var test:Boolean = true;
</script>
]]></html:htmlOverride>
</s:BorderContainer>
Interesting note:
The editor on SO is outdenting when you click code button when the code is already indented.
You could either construct a RegExp object from a template, or you could use the regular expression several times:
var temp:String = '^[\t ]{0,';
function outdent(input:String, amount:Number = 1):String {
return input.replace(new RegExp(temp + amount.toString() + '}', 'gm'), '');
}
Or:
var pattern:RegExp = /^[\t ]/gm;
function outdent(input:String, amount:Number = 1):String {
for (var i:Number = 0; i < amount; i++)
input = input.replace(pattern, '');
return input;
}

Reg-ex query is too greedy

Consider the following snippet:
<Offering id=1 blah blah templateid=abc something=blah
gretre
rtert
ret
tr
/Offering>
<Offering id=2 blah blah templateid=def something=blah>
gretre
rtert
ret
tr
</Offering>
<Offering id=3 blah blah templateid=ghi something=blah>
gretre
rtert
ret
tr
</Offering>
Given that all I know is the template id, I need to return the whole Offering node that contains it. i.e. for templateid=def, I need to return:
<Offering id=2 blah blah templateid=def something=blah>
gretre
rtert
ret
tr
</Offering>
I've tried all sorts but the closest I can get is something along the lines of (?s)<Offering.+?templateid=def.+?</Offering> which returns from the first offering until the end of the offering containing my template id. I understand why but nothing I've tried can fix it. I'm guessing lookarounds but I just can't get it right.
How can I return the whole offering node?
You could modify your regex using negation and I would probably use a word boundary as well.
<Offering[^>]*\btemplateid=def[^>]*>[^<]*</Offering>
If you have other tags inside of this tag, you could do ...
(?s)<Offering[^>]*\btemplateid=def.+?</Offering>
This should work but please notice that I escaped the / character, and you may not need to do that depending on what language you're using:
(<Offering[^>]* templateid=ghi [^>]*>[^<]*<\/Offering>)
As you say you "need to return the whole Offering node", the arguably simpler, safer and more readable way would be a DOM parser. I've included examples of how you might do this in JavaScript and PHP below.
PHP
$doc = new DOMDocument();
#$doc->loadHTML($testStr); //Only needed if you're loading HTML like in the example which has repeated attributes and other things that could cause errors
$body = $doc->getElementsByTagName('body')->item(0);
$templateID = 'def';
$myNode = null;
foreach($body->childNodes as $node)
{
if($node->nodeName=='offering')
{
if($node->attributes->getNamedItem('templateid')->nodeValue == $templateID)
{
$myNode = $node;
}
}
}
//$id = $myNode->attributes->getNamedItem('id')->nodeValue;
//$html = $doc->saveHTML($myNode)
JavaScript
var testStr = document.getElementById('str_container').innerHTML;
var parser = new DOMParser();
var doc = parser.parseFromString(testStr,'text/html');
var templateID = 'def';
var myEl = null;
for(var i=0,c=doc.body.children.length;i<c;i++)
{
if(doc.body.children[i].getAttribute('templateid')===templateID)
{
myEl = doc.body.children[i];
}
}
//var id = myEl.id;
//var html = myEl.outerHTML;
console.log(myEl || 'not found');
JavaScript >= IE8
var testStr = document.getElementById('str_container').innerHTML;
var parser = new DOMParser();
var doc = parser.parseFromString(testStr,'text/html');
var templateID = 'def';
var myEl = doc.body.querySelector('offering[templateid='+templateID+']');
//var id = myEl.id;
//var html = myEl.outerHTML;
console.log(myEl || 'not found');

Capybara: Test for Content in CSS PsuedoElements

I'm working on an app where text conditionally appears in a ::before pseudo element's content property and is rendered on the page. After a code change caused this important text to accidentally disappear, I wanted to be able to write tests that would capture that error if it happened again, but there are challenges grabbing the content from pseudo-selectors. I was looking for something like:
#scss
.content-div {
&.condition-true {
&:before {
content: "conditional text";
}
}
}
#coffeescript
if #someCondition
$('content-div').addClass('condition-true')
else
$('content-div').removeClass('condition-true')
#spec
context "when true" do
it "should have the conditional text" do
# do thing that makes it true
expect( page ).to have_content("conditional text")
end
end
The solution wasn't so easy, and I thought I'd share here and let others comment, or provide other solutions.
I'm using Capybara 2.3.0 and Poltergeist 1.5.1.
The key was passing a block of code to page.evaluate_script, as well as Javascript's getComputedStyle() function.
content_array = page.evaluate_script <<-SCRIPT.strip.gsub(/\s+/,' ')
(function () {
var elementArray = $('.desired-css-selector');
var contentArray = [];
for (var i = 0, tot=elementArray.length; i < tot; i++) {
var content = window.getComputedStyle( elementArray[i], ':before' ).getPropertyValue('content');
contentArray.push(content);
}
return contentArray;
})()
SCRIPT
content_array.each { |c| c.gsub!(/\A'|'\Z/, '') }
expect( content_array ).to include("conditional text")
UPDATE - SIMPLE EXAMPLE:
I've recently had to do a much simpler version of this:
color = page.evaluate_script <<-SCRIPT
(function () {
var element = document.getElementById('hoverme');
var color = window.getComputedStyle( element, ':hover' ).getPropertyValue('color');
return color;
})()
SCRIPT

Quick Rhinomocks Help

Can someone take a look at this code and tell me if there's any obvious reason it shouldn't be working? When service.getResponse is called within my code the mocking framework only returns null, not the object I specified.
[Test]
public void Get_All_Milestones()
{
var mockRepo = new MockRepository();
var service = mockRepo.DynamicMock<IRestfulService>();
var request = new RestRequestObject
{
Password = "testpw!",
UserName = "user",
SecureMode = true,
Url = "www.updatelog.com/",
Command = String.Format("projects/{0}/milestones/list", 123456),
Method = "POST"
};
var response = new RestResponseObject
{
StatusCode = 200,
ErrorsExist = false,
Response =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<milestones type=\"array\">\n <milestone>\n <completed type=\"boolean\">false</completed>\n <created-on type=\"datetime\">2008-10-02T17:37:51Z</created-on>\n <creator-id type=\"integer\">3028235</creator-id>\n <deadline type=\"date\">2008-10-20</deadline>\n <id type=\"integer\">7553836</id>\n <project-id type=\"integer\">123456</project-id>\n <responsible-party-id type=\"integer\">3028295</responsible-party-id>\n <responsible-party-type>Person</responsible-party-type>\n <title>Atb2 Editor Substantially Done</title>\n <wants-notification type=\"boolean\">true</wants-notification>\n </milestone>\n</milestones>\n"
};
using(mockRepo.Record())
{
Expect
.Call(service.GetResponse(request))
.Return(response);
}
using(mockRepo.Playback())
{
var dal = new DataAccess(service);
var result = dal.GetMilestones(123456);
Assert.IsNotNull(result, "The result should not be null.");
Assert.AreNotEqual(0, result.Count, "There should be exactly one item in this list.");
Assert.AreEqual(123456, result[0].ProjectId, "The project ids don't match.");
Assert.AreEqual(7553836, result[0].Id, "The ids don't match.");
}
mockRepo.VerifyAll();
}
A dynamic mock will return null if the input data does not match the expected, so my guess would be that your code is calling service.GetResponse() with different values for the RestRequestObject or that equality for the RestRequestObject does not work as you expect it to.
I think I would try replacing the dynamic mock with a strict mock and look at the error Rhino Mocks returns.