Page MenuHomePhabricator

"In template" lookup logic in nested templates should look at the lowest level of nesting.
Open, Needs TriagePublic


Currently this is the behaviour.

If you ask AWB to lookup in {{foobar}} to make some replacements, and {{foobar}} is nested inside {{barfoo}}, those changes will not be made. To do that, you need to tell to look in both {{barfoo}} AND {{foobar}}, which can create situations where {{barfoo}} happens to have some text that matches what is in {{foobar}}.

E.g. if ask AWB to find/replace X->Y in {{foobar}}, in a situation like this

{{barfoo |1=X |2={{foobar|X}} }}

You get no change. If you ask AWB to find/replace X->Y in {{foobar}} and {{barfoo}}, in the same situation, you will end up with

{{barfoo |1=Y |2={{foobar|Y}} }}

Now I believe it is possible to have a nested logic (in {{barfoo}} > in {{foobar}}, find/replace X->Y) to only replace the X in {{foobar}}, but this is extremely tedious to set up. For instance if you are doing replacement inside infoboxes, you'll need to set up this logic for *each infobox*. If you have 3rd-level, 4th-level nesting situations, then this quickly becomes even more nightmarish.

AWB's behaviour should be tweaked to look at the deepest nesting level e.g. (look in {{foobar}}, no matter how deeply nested it is). Or at least make this sort of "deep" lookup easily doable.

Event Timeline

Headbomb renamed this task from "In template" lookup logic in nested templates should be look at the lowest level of nesting. to "In template" lookup logic in nested templates should look at the lowest level of nesting..Mar 9 2017, 12:10 AM

Yes, you would probably need a rule for unnested and a rule for nested.

I would satisfy the nested scenario with advanced F&R by having:
in template rule
Find = ({{foobar[^}]+)X
Replace = $1Y
regex enabled for Find

By setting ({{foobar[^}]+) or similar you will ensure that only the nested template is matched, actual level of nesting should not matter.

@Rjwilmsi, Yes, but that only works as a straight up find/replace. You can't use that with advanced options and skip conditions.

@Headbomb The example I gave worked for me, on the basis of having one rule for unnested cases, and the second rule with the details provided for nested template cases. Or is your actual need more complex than the example I provide, such that it doesn't work for another reason?

Oh I've got quite complex examples. For instance, I have this "accessdate remover" logic, that removes the access date of citations without urls.


citation/cite book/cite journal/vancite journal/vcite journal





Not contains:


Now if want to run that, and the citation is nested in an infobox, then I could sort of (lazily) modify the logic to have


citation/cite book/cite journal/cite web/ vancite journal/vcite journal/infobox foobar

However, it's possible infobox foobar contains a |url= parameter, and the skip conditions are all messed up. Or if another template in that infobox has an accessdate (e.g. {{cite simbad}}), then it could have its accessdate removed.

As I said, you'd need two rules:

Make the contains:
^(citation|cite book|cite journal|vancite journal|vcite journal)

So you only match unnnested. Rest should be the same.


{{(citation|cite book|cite journal|vancite journal|vcite journal)

Not contains:
{{(citation|cite book|cite journal|vancite journal|vcite journal)[^{}]+\s*((chapter|contribution)-?)?url\s*=\s*(\/\/|http|ftp|\{\{)

({{(?:citation|cite book|cite journal|vancite journal|vcite journal)[^{}]+\|\s*)access(-?)date(\s*)=(\s*)([^(\||\})]*)

as currently.

However, if an infobox has two citation templates in it, or the citation template itself has a nested template, you won't handle everything. A simple custom module would avoid all of the nesting issues:

ArticleText = Tools.NestedTemplateRegex(new List<string>("citation/cite book/cite journal/vancite journal/vcite journal".Split('/'))).Replace(ArticleText, m => {

string templateCall = m.Value;

  Tools.GetTemplateParameterValue(templateCall, "contribution-url").Length == 0 &&
  Tools.GetTemplateParameterValue(templateCall, "contributionurl").Length == 0 &&
  Tools.GetTemplateParameterValue(templateCall, "chapter-url").Length == 0 &&
  Tools.GetTemplateParameterValue(templateCall, "chapterurl").Length == 0 &&
  Tools.GetTemplateParameterValue(templateCall, "URL").Length == 0 &&
  Tools.GetTemplateParameterValue(templateCall, "url").Length == 0
  // UpdateTemplateParameterValue will only change parameter value if it already exists
  Tools.UpdateTemplateParameterValue(templateCall, "accessdate", "");
  Tools.UpdateTemplateParameterValue(templateCall, "access-date", "");

 return templateCall;

I don't know how to use modules, I don't know what that coding language is, I have like 40 "In Cite xxx" subrules (and the one presented above has been simplified for sake of clarity), and I'd need to add 200-300 "In: <Infobox>" logic, on top of any other templates that may have a citation nested within it.

Why can't AWB just get that "Look at the deepest level of nesting" option? This way *everyone* can do this properly with minimal effort?

Rjwilmsi claimed this task.

rev 12148 For T159958 For in template rules, apply rules to all template calls including all nested templates, rather than parent template only

@Rjwilmsi is there a regression here? The latest version seems to not do this anymore.

@Headbomb what's your test case/example that used to work and now doesn't?

Well if you have something like

In template call -- > Cite web -- > Find JPL --> Replace with nothing

and run it on [ you get nothing.

But if you run it on you get something

Headbomb reopened this task as Open.EditedSep 17 2019, 11:30 PM

Re-opened, since this is a regression.

Has somehow been lost along the way, or has been rendered ineffective through some other change. Possibly this one

It's possible that there's a typo somewhere (GetAllTemplateDetail vs GetAllTemplatesDetail), but I don't really understand enough about programming languages to be able to make much sense of the code.