Page MenuHomePhabricator

frame:preprocess does not work when module is called with subst:
Closed, InvalidPublic

Description

assume Module:Thisone

function m.func(frame)
 local t = frame:preprocess(frame.args[1])
 -- do something with expanded template
 return mw.text.nowiki(t)
 end

function makes no sense, but is only provided, to show the problem.

called with {{#invoke:Thisone|func|1={{!}}}} works
called with {{subst:#invoke:Thisone|func|1={{!}}}} template is not expanded in func

Event Timeline

Formatierer raised the priority of this task from to Needs Triage.
Formatierer updated the task description. (Show Details)
Formatierer added a project: Scribunto.
Formatierer subscribed.
Anomie set Security to None.
Anomie claimed this task.
Anomie subscribed.

This is how the parser works: substing happens during the pre-save transform phase, and during that phase the preprocessor doesn't expand non-substed templates. Otherwise you'd wind up with all the templates inside the substed template expanded, which isn't the behavior people have come to expect.

You can see that frame:preprocess during a subst does stuff by passing it template invocations using subst (e.g. frame:preprocess( '{{subst:Test}}' )), ~~~~, and the like.

EDIT: Anomie beat me to it.

First of all, frame:preprocess isn't really intended to ever be called with an already-preprocessed parameter, which anything from frame.args is. That aside, the way preprocess works is that it preprocesses its input in the exact same way that it currently would be outside of a module. Since {{!}} is left alone in wikitext during a pre-save transform, it's also left alone when preprocess is called on it during a pre-save transform. Therefore, I consider this intended behavior rather than a bug. To do what you'd want, you'd have to do frame:preprocess('{{subst:!}}') or its equivalent.

To add to what Anomie and Jackmcbarn said, if you do need to use frame:preprocess with both substitution and transclusion, you can use safesubst. For example, frame:preprocess( '{{safesubst:Test}}' ) will always get you the expanded {{Test}} template.

Not really. What i do need is a version of frame:preprocess where i can control the mode of operation independent from the invocation mode of the module itself. Say a new function frame:expand, which will do that.

see:
https://de.wiktionary.org/wiki/Vorlage:en
https://de.wiktionary.org/wiki/Modul:User:Formatierer/Preprocess
https://de.wiktionary.org/wiki/Modul_Diskussion:User:Formatierer/Preprocess

frame:preprocess operates always in the same mode the module is invoked with.
So if the module is invoked with subst: i get {{#if:|Englisch|[[Englisch]]}} or {{en}}
What i want is [[Englisch]] everytime the module is invoked, independent of the invocation mode.

You need to put safesubst in the template you are trying to substitute as well. In Vorlage:en, change {{#if:{{{nolink|}}}|Englisch|[[Englisch]]}} to {{<includeonly>safesubst:</includeonly>#if:{{{nolink|}}}|Englisch|[[Englisch]]}}, and it should work.

You are right. Thank you for pointing that out. At least i think i understood what preprocess really is doing. In this case, i have to change about 500 language templates according to your advice to get my module working as intended. These templates are very simple, so the change is easy, but time consuming. BUT if the templates i want to process are getting more complex, i have to - eventually recursively - splatter these <includeonly>safesubst:</includeonly> directions around, making the templates more unreadable.
Nevertheless it would be nice to have a function like the above mentioned frame:expand() that would do all that implicitly for me (and perhaps other developers).

Restricted Application added a subscriber: jeblad. · View Herald TranscriptOct 16 2020, 5:28 PM