Page MenuHomePhabricator

Add "JSON with custom renderer" content model
Open, Needs TriagePublicFeature

Description

Inspired by T365803: Turn Interwiki Map page on meta into JSON - it would be nice if it were possible to have a page that was stored as JSON, but when viewed that JSON was passed through a template rather then being rendered as raw JSON to avoid needing separate pages like https://meta.wikimedia.org/wiki/Interwiki_map and https://meta.wikimedia.org/wiki/Interwiki_map/list

The template itself could either be hardcoded as an interface message (which then on the on-wiki side switches based on the page name or structure of the JSON) or be stored as a MCR slot.

Event Timeline

Conceptually related to T206395 but more flexible.

JsonConfig provided a Tabular.JsonConfig data model, but in that data model schema and data is stored in one single page (e.g. https://commons.wikimedia.org/w/index.php?title=Data:Completely_indexed_painters.tab&action=edit). We may reuse the viewer and editor though.

Change #1041816 had a related patch set uploaded (by Pppery; author: Pppery):

[mediawiki/core@master] Add mediawiki message for overriding rendering of JSON

https://gerrit.wikimedia.org/r/1041816

I don't see how a wikitext message or template could generate a custom rendering of a JSON structure. If you supply the JSON as a parameter to the wikitext message, it's just a string. There is no mechanism in wikitext for parsing it, or for iterating over the fields of an array or object. I suppose it might be possible with Lua...

It would make more sense to me to use a Mustache template. Mustache is designed to operated on nested data structures, and the code could pass the data as a nested array to the Mustache processor. We are using this approach for [some parts of some] skins.

The mustache template could generate wikitext or HTML. If we went for HTML, it would have to go through the sanatizer. Or we'd have to require the editinterface permission for editing the mustahce template.

editinterface permission

Anything that would be a potential XSS vector (i.e. allowing arbitrary raw HTMLs) must be gated by both editsitejs and editsitecss rights, if enabled at all. See also https://www.mediawiki.org/wiki/Manual:$wgRawHtmlMessages.

Consider the example in the task description: people wrote a Lua module (https://meta.wikimedia.org/wiki/Module:Interwiki_map) that performs a (relatively trivial) decode and render of JSON at https://meta.wikimedia.org/wiki/Interwiki_map/list to produce a table that will eventually be at https://meta.wikimedia.org/wiki/Interwiki_map. That's what I'm looking for. Adding a mustache templating syntax to the interface, as opposed to merging the eight-line patch above, seems like letting the perfect be the enemy of the good to me. But I guess my perspective is probably by nature biased toward quick fixes rather than long-term solutions as a volunteer coder.

As @Pppery points out in T365847#9886955, today it is possible to connect a JSON content model page, a Scribunto module, and a wikitext content model page to effectively produce a custom rendering of the JSON content. The nice to have addition would be squishing this down such that when you are viewing the rendered page its edit links go directly to the JSON content model editor instead of the wikitext content model editor one would get with the currently possible implementation.

My imagined use cases are pages such as https://wikitech.wikimedia.org/wiki/Deployments where editing the structured JSON content would be the common action and editing the rendering logic would be relatively uncommon. I don't particularly see a need for passing the default HTML output to this custom render layer as the patch at https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1041816 currently does, but maybe I am suffering from a lack of imagination about how that would be helpful.

The implementation that has been floating around in my head is something like a hook that would hand off rendering the content block directly to a Scribunto module with the structured data produced by the JSON content model passed as a single argument to a well-known entry point. From there things would function as though a wikitext page containing something like {{#invoke:My page's custom content renderer|render|$data}} as its content was being processed. See https://toolhub-extension-demo.toolforge.org/wiki/Module:Toolinfo#L-420 and https://toolhub-extension-demo.toolforge.org/wiki/Commons_tools/data/wikimedia-toolhub for one example of the kind of relatively complex rendering this would allow. The structured data in that implementation is actually a horrible abuse of wikitext and lua rather than the more elegant JSON content type imagined here.

The implementation that has been floating around in my head is something like a hook that would hand off rendering the content block directly to a Scribunto module with the structured data produced by the JSON content model passed as a single argument to a well-known entry point.

If we want ot use Scribunto for this, I'd propose to make a hook in core that the Scribunto extension can implement. That hook would allow Scribunto to check whetehr a module slot is associated with the JSON page. And if it is, it gets invoked and the JSON is passed to it directly. The result would be shown instead of the default rendering. That should even work for previews.

This approach would need no new extension, and only a minimal addition to core. It would provide a natural way to attach Lua to the JSON page. The only blocker I see is that EditPage currently only suports the main slot. It would give us an incentive to finally fix that.

The alöternative would eb to use a subpage instead of a slot. It's a bit sad to do that just because EditPage is such a mess that it's hard to make it work for extra slots.

This seems related to the idea of "page data contexts" which has been floating around (eg T122934#9196348), but as a sorted inverted case -- instead of "an article page have a data context attached", this proposal is closer to "a data page with a presentation context attached". I think both are interesting concepts that I'd like to explore, but we don't have anything similar on our current roadmap. @daniel's proposal is workable and is very similar to the "article page with a data context attached", in that if you could associate a scribunto module with a Title, you could execute that scribunto module to generate the 'data context'. But here we want to execute the scribunto module to generate the article page... generating wikitext from lua is something i'm not a huge fan off. See [[Extension:ArrayFunctions]], which would be a way to generate the wikitext from tabular data.

Change #1041816 abandoned by Pppery:

[mediawiki/core@master] Add mediawiki message for overriding rendering of JSON

Reason:

This is clearly not happening this way

https://gerrit.wikimedia.org/r/1041816

Pppery renamed this task from Add "JSON with template renderer" content model to Add "JSON with custom renderer" content model.Tue, Jun 25, 6:17 PM