Page MenuHomePhabricator

Add support for generating static SVG images via Scribunto
Closed, ResolvedPublicFeature

Description

Feature summary and use cases same as T334372: Add support for inline SVG. There was an objection to using that task to discuss a Scribunto solution, so creating a dedicated task.

There's a benefit to doing this through Lua, addressing the following shortcomings of the proposed implementation in core:

  • It uses an <svg> tag in wikitext which mimics the HTML <svg>, but actually outputs an <img>, which is slightly confusing.
  • There's some interest in building an SVG sanitizer (T334953) and emitting <svg> tags directly to wikitext (see T334372#9708574 and other comments), so the SVG-as-image feature probably shouldn't reserve the <svg> markup.
  • There is no natural way to declare attributes for the <img> element. The width and height are set to values passed as <svg> attributes. For class, img-class attribute of <svg> is awkwardly used. Other attributes of <img> like alt= could also be useful. Lua can do this more cleanly (think svg:setAttribute(...) and svg:setImgAttribute(...))
  • The full text of the <svg> tag contributes to PEIS, which could make the feature unfeasible for complex SVGs. A Lua implementation will generate the image tag and replace it with a strip item. Thus, it contributes almost nothing to PEIS. Length of SVGs will only be limited by the unstrip post-expand size of 5 MB and revision size of 2 MB.

Event Timeline

SD0001 renamed this task from Add support for generating static SVG files via Scribunto to Add support for generating static SVG images via Scribunto.Sep 28 2025, 8:20 PM

Proposed Lua interface:

  • Initialize an SVG: local svg = mw.svg.new()
  • Set attributes: svg:setAttribute('width', '120px')
  • Set content: svg:setContent('<circle cx="50" cy="50" r="45" style="fill:green;" />')
  • Set image attributes: svg:setImgAttributes('alt', 'SVG image')
  • Generate: svg:toImage()

In the future if necessary, svg:toTag() could be implemented to sanitize and output the svg tag directly.

Change #1191862 had a related patch set uploaded (by SD0001; author: SD0001):

[mediawiki/extensions/Scribunto@master] Add support for generating static SVG images

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

I don't think that allowing {{#invoke:}}d Lua functions to have side effects, that is, effects other than their return injected into wikitext, is a good idea.

The only exception could be Lua functions changing some attributes of the pages where they are called; like parser function can.

In this case, creation of a .png image would such an effect.

The only exception could be Lua functions changing some attributes of the pages where they are called; like parser function can.

I don't think the proposed patch does that. It looks like it generates a data url.

(There are things that do that though. <easytimeline>. Historically <math> did).

The only exception could be Lua functions changing some attributes of the pages where they are called; like parser function can.

Historically <math> did).

And graphviz.

I don't think that allowing {{#invoke:}}d Lua functions to have side effects, that is, effects other than their return injected into wikitext, is a good idea.

In this case, creation of a .png image would such an effect.

The proposed patch doesn't create any png file. It produces a SVG image using <img> element with src set to a base64-encoded data url.

Even if it did, I don't see anything wrong with the "side effect" of creating a file. In addition to the tags mentioned above, <score> and <phonos> do it as well.

Test wiki created on Patch demo by SD0001 using patch(es) linked to this task:
https://f46dc82dd5.catalyst.wmcloud.org/w/

Change #1191862 merged by jenkins-bot:

[mediawiki/extensions/Scribunto@master] Add support for generating static SVG images

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

Pppery subscribed.

This definitely deserves a tech news entry

Thanks a lot! Unfortunately, looks like there is no way to fetch a code of svg file in Lua, so it will work only for inline hardcoded svg or wikitext pages. Is there any intention to change it in the future? I couldn't find any open task in Phabricator.

Are the :set... methods not chainable?

Can we feature this in Tech News and how do we word it?

You can use MediaWiki:User:IKhitron/Sandbox with examples that I've made for myself, if you want.

I think the next obvious question is can we make mw.title.new("Media:foo.svg"):getContent() return the text of the svg if the file is below a certain size. Then we could have lua do post processing on svg files, to e.g. change the colour of something.

More generally it would be kind of cool to allow lua access to (small) uploaded files. You could imagine allowing uploads of csv files as an alternative to jsonData.

I think the next obvious question is can we make mw.title.new("Media:foo.svg"):getContent() return the text of the svg

A more reasonable API might be as part of file metadata: mw.title.new("File:foo.svg").file.source, so that's it's recorded as a file usage. Or even better: mw.svg.newFromFile("foo.svg").

Alternatively, I wonder if we could have svg as a content model so that we can store semi-formed SVG "templates" with syntax highlighting etc (and read them as regular pages), which may be a better approach than manipulating a fully-formed svg uploaded as a file.

Alternatively, I wonder if we could have svg as a content model so that we can store semi-formed SVG "templates" with syntax highlighting etc (and read them as regular pages), which may be a better approach than manipulating a fully-formed svg uploaded as a file.

I saw a task to create a way for svg file versions diff years ago. This can make that task much easier.

Bawolff assigned this task to SD0001.

[Forgive me if this is off topic] Some experiments taking images from the Animated_SVGs category on commons: https://en.wikipedia.org/wiki/Module:Sandbox/Bawolff/interactiveSvg

I'm excited about the possibilities here.

Can we feature this in Tech News and how do we word it?

Something along the lines of "Scribunto modules can now be used to generate SVG images. This can be used to build charts, graphics and other visualizations dynamically through Lua, reducing the need to compose them externally and upload them as files."

I created some follow-up tasks based on the conversation here: T407710, T407709 (the latter one with a POC patch!)

Another interesting idea would be if there could be some :addVariables() lua call, which would inject into the svg a style tag containing all the skin's css color variables (e.g. --color-base et al). Probably kind of hard at the moment due to the way skins are structured.

Quiddity subscribed.

I think this feature sounds exciting, per your comments and linked-experiments above, and I worry the current draft-entry, and the documentation it links to, doesn't communicate that clearly to newcomers to this feature. In particular, the documentation doesn't seem to contain any specific examples of how this can be used. We don't usually link to user-sandboxes, especially English-language-only ones, so that's not a great option.
How could we improve the announcement, and the linked documentation, so that the powerful possibilities are more obvious to readers?

Scribunto modules can now be used to generate SVG images. This can be used to build charts, graphics and other visualizations dynamically through Lua, reducing the need to compose them externally and upload them as files.

The stuff in my subpage is kind of cool demos but probably not the features envisioned usecase.

Normally we keep LUAREF kind of concise, perhaps a subpage with more details would make sense.

I think this feature sounds exciting, per your comments and linked-experiments above, and I worry the current draft-entry, and the documentation it links to, doesn't communicate that clearly to newcomers to this feature. In particular, the documentation doesn't seem to contain any specific examples of how this can be used. We don't usually link to user-sandboxes, especially English-language-only ones, so that's not a great option.
How could we improve the announcement, and the linked documentation, so that the powerful possibilities are more obvious to readers?

Scribunto modules can now be used to generate SVG images. This can be used to build charts, graphics and other visualizations dynamically through Lua, reducing the need to compose them externally and upload them as files.

I tried to add an additional example of a graph at https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#mw.svg.new . The ability to dynamically make graphs is the primary expected use case (Animations are cool and are, but are more pretty to look at than actually useful for an encyclopedia, so i think we should focus on the graphs aspect)

In this solution, SVG is treated like a monolith. Perhaps, it structure could be represented by nested Lua tables corresponging to nested SVG elements?

I did a quick PoC to replace Pie chart with SVG. This is a no go unfortunately.

  1. Hover doesn't work so not able to highlight anything.
  2. Tooltips doesn't work either.

The limitations (for readers) are pretty much the same as in T334372: Add support for inline SVG.

In this solution, SVG is treated like a monolith. Perhaps, it structure could be represented by nested Lua tables corresponging to nested SVG elements?

Maybe it should expose something like mw.html esque interface.

I did a quick PoC to replace Pie chart with SVG. This is a no go unfortunately.

  1. Hover doesn't work so not able to highlight anything.
  2. Tooltips doesn't work either.

The limitations (for readers) are pretty much the same as in T334372: Add support for inline SVG.

There is a potential work around of composing multiple svgs as different layers, but its a bit messy

  1. Hover doesn't work so not able to highlight anything.
  2. Tooltips doesn't work either.

These use cases will be supported in T407783, the other approach, although that may come at the cost of not being able to support certain other features, based on limitations of our sanitizer.

Regarding Tech News, I will move forward with this draft with @Bawolff's additional graph example in the manual. Thanks all.

I think this feature sounds exciting, per your comments and linked-experiments above, and I worry the current draft-entry, and the documentation it links to, doesn't communicate that clearly to newcomers to this feature. In particular, the documentation doesn't seem to contain any specific examples of how this can be used. We don't usually link to user-sandboxes, especially English-language-only ones, so that's not a great option.
How could we improve the announcement, and the linked documentation, so that the powerful possibilities are more obvious to readers?

Scribunto modules can now be used to generate SVG images. This can be used to build charts, graphics and other visualizations dynamically through Lua, reducing the need to compose them externally and upload them as files.

I tried to add an additional example of a graph at https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#mw.svg.new . The ability to dynamically make graphs is the primary expected use case (Animations are cool and are, but are more pretty to look at than actually useful for an encyclopedia, so i think we should focus on the graphs aspect)

For a non-graph example, I made a template that can render molecules using this feature - https://en.wikipedia.org/wiki/Module:CineMol . Its a very open-ended feature, so your imagination is really the limit.