Page MenuHomePhabricator

Parametric JSON builder
Closed, DeclinedPublic

Description

@GWicke has repeatedly said that he is not happy when JSON is created via template parameter expansion, as used by the <graph> tag:

<graph>{
  "a": "{{{templateArgA}}}",
  "b": {{{templateArgB | { } }}}
}</graph>

I would somewhat agree that having an arbitrary text expansion seems ripe for abuse, yet at the same time offers tremendous power that has been heavily used by many templates, along side Lua JSON generation.

I'm starting this RFC to find a better middle ground that offers both the power and flexibility, while also being more palatable architecturally and easier to use for Parsoid et al.

Technically, template param expansion is similar to a User Defined Function - where Wiki contributors define a custom function that takes some arguments, and generates a valid JSON blob. Assuming that HTML tag attributes could have any length, the above example can be written as:

<graph argA='"{{{templateArgA}}}"' argB="{{{templateArgB | { } }}}" >{
  "a": (argA),
  "b": (argB)
}</graph>

where the argA and argB are first resolved by the Parser. The JSON generator then requires each argument to be a valid JSON (a properly quoted string, number, list, object, null, true, false). Each argument placeholder can only be placed in the "valid" JSON value spots:

{
  "a": (argA),      // valid
  "b": "(argB)",    // ignored
  "c": (argC).5,    // not valid - concatenating two part of a number
   ...
}

The problem with this approach is that most likely the community will immediately want conditionals, e.g. insert argA only if argA is given, otherwise don't even add the "a" element.

Optionally we might also want to support comma-separated list of JSON, allowing authors to write "c": [ (argA), (argB) ] (list concatenation), or `"d": { (argA), (argB) } (object property merging). This is TBD, possibly not worth it because it can be done with Lua.

Given this generic facility, we could disable any kinds of template parameter expansion inside the tag (after some migration time).

Event Timeline

Yurik raised the priority of this task from to Needs Triage.
Yurik updated the task description. (Show Details)
Yurik added projects: TechCom-RFC, Proposal.
Yurik added subscribers: Yurik, GWicke.

From IRC, @GWicke suggested looking at npm json templates and Jinja2.

A few additional thoughts:

  • this has to be implemented and kept in sync for both MediaWiki and NodeJS
  • Should the non-expanded template be a valid JSON? Or should we explicitly make all template values stand out and break the JSON spec until the expansion is done? I would prefer the later as to avoid accidental expansions/non-expansions.

A clean separation between the API / data massaging layer and presentation layer would avoid a lot of the invalidation & size issues graphs currently have.

JSON templating solutions and / or other data transform libraries could potentially be used to provide a sane (ideally standardized) data format as an API, and graphs could then reference this data & parametrize the presentation by supplying options to preset graph definitions.

RobLa-WMF mentioned this in Unknown Object (Event).May 4 2016, 7:33 PM

I think we can close this because I have disabled this in production anyway - we now use

{{#tag:graph|
{
  "a": "{{{templateArgA}}}",
  "b": {{{templateArgB | { } }}}
}
}}

Resolved per Yuri's last comment (as the author). We don't have a "withdrawn" status, so I'm using "declined" as a substitute.