Page MenuHomePhabricator

Should we consider supporting skins that render content in other formats e.g. JSON in addition to HTML via Mustache templates?
Closed, ResolvedPublicFeature

Description

NOTE: This relates to a third party extension and I am requesting this feature/clarity as a volunteer, not as a WMF staff member.

Feature summary (what you would like to be able to do and where):
A while ago I made the SkinJSON skin. It renders Skin::getTemplateData (which is a data object passed as input to a Mustache template) as JSON so it can be used as an API or as a reference to skin developers. It is built as a skin rather than an API, as in my attempts to replicate it within the context of an API I was unable to reliably replicate all the hooks/side effects of a skin.

In T306942 we plan to limit skins to rendering the BODY tag of MediaWiki - this constraint should reduce the amount of power skins have traditionally yielded - for example disabling ResourceLoader and adding their own style/script tags which creates an unexpected environment. This would break SkinJSON without a migration path.

I am curious on advice about whether it would make sense to skins that output in formats different to HTML.

Use case(s) (list the steps that you performed to discover that problem, and describe the actual underlying problem which you want to solve. Do not describe only a solution):

  • Rendering template data as a JSON in the browser (basically SkinJson use case): this is currently done by SkinJSON using the following hack:

https://github.com/jdlrobson/mediawiki-skins-skinjson/blob/master/SkinJSON.php#L312
It would be nice if instead, SkinJSON could declare its content type to avoid having to do this. It would likely need to be done in the communication between OutputPage and Skin.php

Other hypothetical use cases that might be useful:

  • Rendering ATOM feeds
  • Rendering content types other than wikitext in their native format.
  • In future perhaps this could be used for API e.g. skinversion=3 to support different versioned formats e.g. the skin layer could pull out existing logic for skinversion=2 from the API e.g. mapping Objects to arrays and it would be easier for 3rd parties that want custom APIs to use the skinning layer to render JSON in different desired output.

Benefits (why should this be implemented?):

  • Rendering things in a format other than HTML fits the mould of what I would expect a Skin to be able to do.
  • It's clearer what the boundaries of a skin are

Event Timeline

I'm not sure I properly understand the use case. What would consume that JSON?

This reminds me of an exploration that @santhosh worked on a couple of years ago, a "content model" for page views. The idea I believe was a kind of "backend for frontend" API for driving cvlient side skinning. Is that the kind of thing you ware thinking of?

I'm not sure I properly understand the use case. What would consume that JSON?

The main use case for https://github.com/jdlrobson/mediawiki-skins-skinjson/blob/master/SkinJSON.php#L312 is that skin developers want to debug/learn about the internal skin API e.g. the template properties that get sent to a Mustache template for rendering either via a browser extension for prettifying JSON in your browser tab or in an app that utilizes this such as https://skins.wmcloud.org/#/add (scroll down to the "Template data" section)

This reminds me of an exploration that @santhosh worked on a couple of years ago, a "content model" for page views. The idea I believe was a kind of "backend for frontend" API for driving cvlient side skinning. Is that the kind of thing you ware thinking of?

This is also another valid use case. If this API response was also cached, this would allow skins to render via JSON (without a page reload)as the response would provide the exact information needed to render a page. This is actually in use on the Alexandria skin.

In general, we need an API for rendering skin template data as JSON - that would make the SkinJSON skin defunct and unnecessary if it existed, but it would not allow the use cases in the description such as skinning RSS feeds or providing custom JSON responses.

I'm not sure I properly understand the use case. What would consume that JSON?

The main use case for https://github.com/jdlrobson/mediawiki-skins-skinjson/blob/master/SkinJSON.php#L312 is that skin developers want to debug/learn about the internal skin API e.g. the template properties that get sent to a Mustache template for rendering either via a browser extension for prettifying JSON in your browser tab or in an app that utilizes this such as https://skins.wmcloud.org/#/add (scroll down to the "Template data" section)

Ah, so this is about the data fed to mustache templates, not about TemplateData for wikitext. That makes more sense. Can you add the word "Mustache" to the task description somewhere?

In general, we need an API for rendering skin template data as JSON - that would make the SkinJSON skin defunct and unnecessary if it existed, but it would not allow the use cases in the description such as skinning RSS feeds or providing custom JSON responses.

Thinking as this of an API that exposes the data model used for rendering skins makes more sense to me than thinking of it as a "skin that renders JSON". That may in fact be how we implement it internally, but it seems like we wouldn't want to expose it that way.

But then, maybe useskin=json could be much like uselang=qqx - a little hack useful for debugging and exploration. As a development tool it actually sounds kind of nifty. But if it is supposed to act as any kind of stable interface consumed by software, we should provide a REST endpoint instead.

Jdlrobson renamed this task from Should we consider supporting skins that render content other than HTML? to Should we consider supporting skins that render content in other formats e.g. JSON in addition to HTML via Mustache templates?.May 23 2024, 3:47 PM
Jdlrobson updated the task description. (Show Details)

But then, maybe useskin=json could be much like uselang=qqx - a little hack useful for debugging and exploration. As a development tool it actually sounds kind of nifty. But if it is supposed to act as any kind of stable interface consumed by software, we should provide a REST endpoint instead.

I would say the main usage right now is for development - skin developers often need to find out how to render something passed down from MediaWiki core. It would be nice if this was a core feature as I agree it is helpful. We could limit it to development environments behind a feature flag to avoid it becoming used as an API as I would say that's an interesting use case but not.

I've done a POC of what this would look like here: https://gerrit.wikimedia.org/r/c/mediawiki/core/ /1035480
If you think that looks like a good approach I'll create a ticket capturing this particularly use case and remove the POC tag, T306942 will be unblocked; I'll dismantle the SkinJSON skin since it would now be obsolete; and we can decline this ticket.

I've done a POC of what this would look like here: https://gerrit.wikimedia.org/r/c/mediawiki/core/ /1035480
If you think that looks like a good approach I'll create a ticket capturing this particularly use case and remove the POC tag, T306942 will be unblocked; I'll dismantle the SkinJSON skin since it would now be obsolete; and we can decline this ticket.

I prefer a separate skin for JSON output over a mode supported by all skins... The output would be the same for all skins, right?

In T306942 we plan to limit skins to rendering the BODY tag of MediaWiki - this constraint should reduce the amount of power skins have traditionally yielded - for example disabling ResourceLoader and adding their own style/script tags which creates an unexpected environment. This would break SkinJSON without a migration path.

I think the concept of output format could exist internally. If SkinJSON declares that it outputs JSON rather than HTML, so the calling code doesn't try to wrap the content, that would solve the problem, right?

I prefer a separate skin for JSON output over a mode supported by all skins... The output would be the same for all skins, right?

Something like this? https://gerrit.wikimedia.org/r/c/mediawiki/core/ /1036736

Change #1036736 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/core@master] [POC 2] Skins: Support useskin=json

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

This approach seems good for creating a "skin" that allows developers to "eyeball" the data passed to the skin, for exploration and debugging. It should be clear that the output is for human consumption, though.

I didn't realize that we already have an "apioutput" skin... I suppose it exists to support things like loading updates for Special:RecentChanges? That sounds... terrible.

One component of the ideas we came up with during the the FAWG exploration was a "snippet API" that could be used to ask MediaWiki for bits of HTML. Imagine a REST API with paths like this: /api/skin.v1/snippet/Special/RecentChanges or /api/skin.v1/snippet/portlet/user-menu.

This approach seems good for creating a "skin" that allows developers to "eyeball" the data passed to the skin, for exploration and debugging. It should be clear that the output is for human consumption, though.

I think we could limit this to a feature flag similar to JavaScript/qunit/test - would that make sense?

This approach seems good for creating a "skin" that allows developers to "eyeball" the data passed to the skin, for exploration and debugging. It should be clear that the output is for human consumption, though.

I think we could limit this to a feature flag similar to JavaScript/qunit/test - would that make sense?

In my experience, it's quite useful to avoid this kind of debugging tool (like uslang=qqx) available for the live site. But you know the potential use cases betetr that I do.

Change #1036736 merged by jenkins-bot:

[mediawiki/core@master] Skins: Support useskin=json

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

Jdlrobson claimed this task.

Change #1051494 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/core@master] Hide Skin JSON from Special:Preferences

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

Change #1051494 merged by jenkins-bot:

[mediawiki/core@master] ServiceWiring: Hide Skin Json from Special:Preferences

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