New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add url REPLACE macro #13130
Add url REPLACE macro #13130
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,6 +98,17 @@ function defaultMacro(value, defaultValue) { | |
return value; | ||
} | ||
|
||
function replaceFilter(string, matchPattern, newSubStr) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. jsDoc There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops. Done. |
||
if (!matchPattern) { | ||
user().warn(TAG, 'Replace must have two or more arguments'); | ||
} | ||
if (!newSubStr) { | ||
newSubStr = ''; | ||
} | ||
const regex = new RegExp(matchPattern, 'g'); | ||
return string.replace(regex, newSubStr); | ||
} | ||
|
||
|
||
/** | ||
* Provides support for processing of advanced variable syntax like nested | ||
|
@@ -126,6 +137,7 @@ export class VariableService { | |
this.register_('HASH', this.hashMacro_.bind(this)); | ||
this.register_('IF', | ||
(value, thenValue, elseValue) => value ? thenValue : elseValue); | ||
this.register_('REPLACE', replaceFilter); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ | |
|
||
import {rethrowAsync} from '../../log'; | ||
|
||
export const PARSER_IGNORE_FLAG = '`'; | ||
|
||
/** Rudamentary parser to handle nested Url replacement. */ | ||
export class Expander { | ||
|
||
|
@@ -86,13 +88,13 @@ export class Expander { | |
let matchIndex = 0; | ||
let match = matches[matchIndex]; | ||
let numOfPendingCalls = 0; | ||
let ignoringChars = false; | ||
|
||
const evaluateNextLevel = () => { | ||
let builder = ''; | ||
const results = []; | ||
|
||
while (urlIndex < url.length && matchIndex <= matches.length) { | ||
|
||
if (match && urlIndex === match.start) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can we get a match in the middle of a literal string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand your question correctly, this is to support things like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I mean why would
the tick marks a literal string ("don't parse me" section). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the way it was designed is so that the ticks are only respected inside a macro call (inside parenthesis). We are currently reserving keywords like |
||
let binding; | ||
// find out where this keyword is coming from | ||
|
@@ -127,7 +129,12 @@ export class Expander { | |
builder = ''; | ||
} | ||
|
||
else if (numOfPendingCalls && url[urlIndex] === ',') { | ||
else if (url[urlIndex] === PARSER_IGNORE_FLAG) { | ||
ignoringChars = !ignoringChars; | ||
urlIndex++; | ||
} | ||
|
||
else if (numOfPendingCalls && url[urlIndex] === ',' && !ignoringChars) { | ||
if (builder.length) { | ||
results.push(builder.trim()); | ||
} | ||
|
@@ -141,7 +148,7 @@ export class Expander { | |
urlIndex++; | ||
} | ||
|
||
else if (url[urlIndex] === ')') { | ||
else if (url[urlIndex] === ')' && !ignoringChars) { | ||
urlIndex++; | ||
numOfPendingCalls--; | ||
const binding = stack.pop(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i thought this should gives
this is a test
(with spaces)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are currently stripping spaces so people can do things like
DEFAULT(one, two)
vs only allowingDEFAULT(one,two)
. We could change this but I think allowing it is better? It does make it tricky to pass in a space thoughThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that both tests are testing replace with no third arg? here
newSubStr = undefined
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no,
newSubStr === ''
in the first. I will add a few more tests to make this more clearThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so how do i get
this is a test
? Is it supported?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was spending some time thinking about this last night. Right now it is not supported without using a different macro that would return a space. We could support something like
REPLACE(this-is-a-test, `-`, ` `)
If we do that should we make the back ticks on the third parameter required? Also no matter what the spaces will be encoded so it would returnthis%20is%20a%20test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are now respecting whitespaces inside all back ticks. More tests were written to cover this behavior.