Page MenuHomePhabricator

Provide a clearer way to distinguish between "absent" and empty/blank parameters when handling them in templates and parser functions
Open, Needs TriagePublic

Description

The concern:

Currently in handling template parameters there is the option to use {{{1}}} which uses a value which is supplied or
{{{1|default}}}. In most instances this suffices.

However, in a series of nested templates, where the first template is a higher level template which in some use cases acts as pre-processor for lower level ones. you end up with constructions like this...

{{sub-template|required=foo|optional={{{optional|}}}}}

Which rather than passing an absence in the event of "optional" to the hgher level template, passes a "".

This as I understand it is working as designed, but makes it less clear for those trying to write, debug or maintain the templates.

Current Outcome

{{{1|deafult}}} generates "default" if the parameter 1 is NOT supplied. However if 1 is blank i.e "" that is what is passed.

See below for a link to a minimal testcase and comparison with the output from a template that "cooks" it's input parameter.

Desired Outcome

On English Wikisource, I'd written https://en.wikisource.org/wiki/Template:Sanenull using parser functions to "force" known values for blank, empty and null values, in attempt to handle this situation, but it uses 2 additional parser function calls which in a complex template would be a performance issue. I am strongly of the view that having {{{#sane:parameter}}} handling would be desirable. A further discussion as to what "sane" values to use as defaults for nulls or blanks could be had..

Alternatively for the use case above would some kind of {{{#pass:parameter}}} or {{#thru:paramater}}} be possible to provide? which would be intended to pass through certain parameters if they existed, or absent them from the call to a sub-template if they were not specified for the higher level one.

The intended construction (in a relevant template being)

{{sub-template|required=foo|optional ={{{#pass:optional}}} }}

If there's an actual value (or an explicit blank "") for optional specfied it gets passed, but if it's never specified, optional is NEVER in the list of parameters passed to the sub template, allowing the existing handling in respect of default values to be used in that sub template as at present.

Having functions like this would make writing 'nested' templates somewhat clearer....

Event Timeline

ShakespeareFan00 lowered the priority of this task from Low to Lowest.
ShakespeareFan00 updated the task description. (Show Details)
Aklapper renamed this task from Provide a clearer way to distinguish between "absent" and emtpy/blank parameters when handling them in templates, and parser functions... to Provide a clearer way to distinguish between "absent" and empty/blank parameters when handling them in templates and parser functions.Jun 5 2018, 10:07 AM

In regard to reproducing the concern in it's simplest form is there a test wiki I can put a minimal template example on?

Okay I added a minimal example here -
https://en.wikisource.org/wiki/User:ShakespeareFan00/foo/bar
https://en.wikisource.org/wiki/User:ShakespeareFan00/foo/testcases

I also for comparison add some test cases for
https://en.wikisource.org/wiki/Template:Sanenull
User:ShakespeareFan00/sanenull-x

These could be implemented internally rather than being templates. I'm not sure pass-thru for certain templates could be implemented though, so will need more time to formulate something....

In regard to the comments about a {{pass:parameter}} Let me provide an example

Template markup for {{foo}}:

{{bar|required|{{pass:optional}}}}

When subsequently callled:

{{foo|required|optional=1}}
{{foo|required}}

What should be called in each instance should be :

{{bar|required|optional=1}}
{{bar|required}}

Currently I don't think the parser can make such a substitution automatically..

More than willing to file this as a seperate ehancement request if desirable

In regard to the comments about a {{pass:parameter}} Let me provide an example

Template markup for {{foo}}:

{{bar|required|{{pass:optional}}

When subsequently callled:

{{foo|required|optional=1}}
{{foo|required}}

What should be called in each instance should be :

{{bar|required|optional=1}}
{{bar|required}}

Currently I don't think the parser can make such a substitution automatically..

And further a real world example.
{{#switch: {{NAMESPACE}}<!--
-->|Page={{float left|{{{1|0}}}|{{{2|0}}}|{{{3|0}}}|{{{4|0}}}|{{{style|}}}|{{{id|}}}}}<!--
-->|#default={{float right|{{{1|0}}}|{{{2|0}}}|{{{3|0}}}|{{{4|0}}}|{{{style|}}}|{{{id|}}}}}<!--
-->}}<!--

should be instead

{{#switch: {{NAMESPACE}}<!--
-->|Page={{float left|{{{pass:}}}|{{{pass:2}}}|{{{pass:3}}}|{{{pass:4}}}|{{{style|}}}|{{{id|}}}}}<!--
-->|#default={{float right|{{{pass:1}}}|{{{pass:2}}}|{{{pass:3}}}|{{{pass:4}}}|{{{style|}}}|{{{id|}}}}}<!--
-->}}<!--

Vvjjkkii renamed this task from Provide a clearer way to distinguish between "absent" and empty/blank parameters when handling them in templates and parser functions to nmbaaaaaaa.Jul 1 2018, 1:06 AM
Vvjjkkii raised the priority of this task from Lowest to High.
Vvjjkkii updated the task description. (Show Details)
Vvjjkkii removed a subscriber: Aklapper.
Wargo renamed this task from nmbaaaaaaa to Provide a clearer way to distinguish between "absent" and empty/blank parameters when handling them in templates and parser functions.Jul 1 2018, 10:34 AM
Wargo lowered the priority of this task from High to Lowest.
Wargo updated the task description. (Show Details)
Wargo added a subscriber: Aklapper.
ShakespeareFan00 raised the priority of this task from Lowest to Needs Triage.Jul 1 2018, 10:52 PM

This vaguely reminds me of a loose end in the heredoc syntax, described in T114432#4717140 -- which is to say, we don't have a good way to flag expansions which are supposed to be an "argument list" vs "literal text". Instead of:

{{templateName|optional ={{{#pass:optional}}} }}

I think what we want is a way to generate a list of arguments, including optional=<some value>, and then to pass that list to templateName.

{{templateName|{{#filter-arglist|optional|{{#arglist}}}}}}

where {{#arglist}} generates the full list of arguments to this function, as a typed/structured object and the {{#filter-arglist}} built-in will extract only the requested ones. When passing an value of this type to a function is gets expanded like a splat so the called template sees the full list as separate arguments.

This is just a strawman, feel free to poke holes. But I agree there's a missing corner in parameter passing here we should try to fill in.

Note that in the common case we just want to pass our argument list down to a subtemplate unmodified, for example to refactor some common processing. This is pretty awkward currently (ie https://en.wikisource.org/w/index.php?title=Template:Lang/new&action=edit ) but could be as simple as:

{{subtemplate|{{#arglist}}}}

in the proposed strawman syntax.

See also T162375, which was a request for an explict way to indicate null values..