Wikipedia talk:Lua/Archive 12#A new template parser
{{Talkarchive}}
nbsp
Easy question this time: how do I produce a non-breaking space in lua? — Martin (MSGJ · talk) 19:50, 12 June 2023 (UTC)
:
?
:—Trappist the monk (talk) 20:35, 12 June 2023 (UTC)
::Thank you. For some reason I thought that would produce the literal text. — Martin (MSGJ · talk) 21:06, 12 June 2023 (UTC)
:::It will produce the literal text
. Presumably, that will then be passed to a browser or similar software which will render it as a space. Lua doesn't have to do anything clever to achieve that. Certes (talk) 21:50, 12 June 2023 (UTC)
Help with Module:Location map
Hello.
I encountered a problem after uploading a map that uses Module:Location map, and was hoping to get help with it.
The file I uploaded is a close-up location map of Cairo and Giza, Egypt, to use it in articles such as 2023–24 Egyptian Premier League and 2023–24 Egyptian Second Division A, to indicate where each club is exactly located, since there are multiple clubs from these two governorates playing in the leagues (something similar to London in Premier League seasons' articles).
Once I uploaded the map and tried to use it, the following error appears:
{{color|red|Lua error in Module:Location_map/multi at line 27: Unable to find the specified location map definition: "Module:Location map/data/Egypt Cairo Giza" does not exist.}}
That error is clickable while in preview. When I click on it, a list of script errors appears, and to be honest, I have no clue how to solve these errors, as I have close to 0 experience with programming languages.
Can someone tell me what exactly I'm supposed to do to fix it? I'd really appreciate that. Thanks. Ben5218 (talk) 10:53, 15 June 2023 (UTC)
:It's looking for a definition in Module:Location map/data/Egypt Cairo Giza. Pleasee see the documentation at Template:Location map — Martin (MSGJ · talk) 11:17, 15 June 2023 (UTC)
::Thank you, MSGJ. I'll check it out. Instructions about everything I have to do should be located there and at Template:Location map/Creating a new map definition, right? Ben5218 (talk) 11:41, 15 June 2023 (UTC)
Read data outside the module namespace
Is there something like Module:Data that can parse JSON outside the module namespace? Specifically, I'd like to work with Wikipedia:New pages patrol/Backlog chart/daily in a template. – Joe (talk) 08:07, 19 June 2023 (UTC)
:I believe the answer is no. A typical use is at {{tl|London ward populations}} which reads items from Module:Data/London ward populations based on a key supplied as a parameter to the template. In other words, Module:Data requires a Lua table. However, a dedicated module could extract data from Wikipedia:New pages patrol/Backlog chart/daily rather easily. What do you need? Johnuniq (talk) 08:28, 19 June 2023 (UTC)
::Well ideally, something like
and
, for an arbitrary date. Or would it be feasible to move the daily stats to the module namespace, {{u|MusikAnimal}}? – Joe (talk) 08:45, 19 June 2023 (UTC)
:::More than moving it would be required. The wikitext at Wikipedia:New pages patrol/Backlog chart/daily is currently in JSON. Module:Data needs the information stored as a Lua table. That's easy but MusikAnimal may not have much spare time. Are you saying you want a new template ({{tlf|NPP backlog size}}) and it should accept, for example, 2022-12-16 as a parameter and return 1355? What would your redirect template do? Johnuniq (talk) 08:53, 19 June 2023 (UTC)
::::Exactly. NPP used to rely quite heavily on Wikipedia:New pages patrol/Backlog chart to keep an eye on whether the backlog was growing or not. Since the graph extension doesn't appear to be coming back any time soon, I'm trying to put together a text-based 'dashboard' that could fulfil the same purpose. It would state the current size of the backlog (from User:DatBot/newpagesbacklog) and how much it is up/down compared to yesterday/last week/last month, sort of like a stock ticker. The "redirect" part is aspirational because as far as I can tell MusikBot doesn't track the size of the unreviewed redirect backlog (though the [https://en.wikipedia.org/w/api.php?action=pagetriagestats API does]). – Joe (talk) 09:04, 19 June 2023 (UTC)
:::::There is no need to look at the following links—I'm mentioning them for background if needed. {{u|GreenC}} and I cooperated on {{tl|NUMBEROF}} which uses Module:NUMBEROF to read values written by a bot to c:Data:Wikipedia statistics/data.tab (Module:NUMBEROF/data translates that page into a Lua table). If the NPP info were written to Commons in a similar way, it would be easy for a module to extract any data required. A bot could also write data from the API (a module cannot access the API). I suggest you prepare a draft of what would be wanted in a sandbox using some of the current data. If you show the output that is wanted, it would be easier for people here to see what is needed. It might be easier for a module to return the whole wanted wikitext rather than implement a template which extracts items one-by-one. Johnuniq (talk) 09:19, 19 June 2023 (UTC)
:mw.loadJsonData
will read data in JSON format, and I think it will happily read from any page in that format, regardless of namespace. For example Module:Class reads the data at Module:Class/definition.json — Martin (MSGJ · talk) 09:20, 19 June 2023 (UTC)
::Oh! I haven't been paying attention to new features. That makes reading the existing page even easier and means adding structured data at Commons is probably not required. A draft of the wanted output would still be desirable. Johnuniq (talk) 09:33, 19 June 2023 (UTC)
::Putting the data on Commons is still sounds like a nice idea in the long term; this is a useful dataset that can't, as far as I know, be extracted from the database retrospectively. But as you say that'd require some bot work. For now, mw.loadJsonData did the trick. Thanks for the help, both! – Joe (talk) 10:46, 19 June 2023 (UTC)
Calculation in string
I have something like '2+3' stored as a string and I would like to calculate it as a number. tonumber
doesn't work here. What's the best method? — Martin (MSGJ · talk) 09:09, 26 June 2023 (UTC)
:tonumber
won't work as it doesn't attempt to evaluate the expression. A quick glance at mw:Extension:Scribunto/Lua reference manual brings up mw.ext.ParserFunctions.expr(string)
, which works like the
parser function and would likely work for your scenario. Aidan9382 (talk) 09:25, 26 June 2023 (UTC)
::And there is an example at Module:Math#L-605. Johnuniq (talk) 09:57, 26 June 2023 (UTC)
::Thanks, that's working nicely — Martin (MSGJ · talk) 11:25, 26 June 2023 (UTC)
:::depending on the source of the string and how much control you have over it, you may want to wrap it in pcall().
:::mw.ext.ParserFunctions.expr("my father is a holy man")
, like any input that won't compute (e.g. 14 / 0) will throw an error.
:::it is preferable to do something like
local okeydokey, result = pcall( mw.ext.ParserFunctions.expr, myExpressionVar )
if okeydokey then
-- in this scope, "result" is good
else
-- handle the error here, like
result = someDefaultValue
end
:::peace - קיפודנחש (aka kipod) (talk) 20:15, 30 June 2023 (UTC)
::::Umm, are you sure? false
for okeydokey
and nil
for result
. Shouldn't the test be: not
token)?
::::—Trappist the monk (talk) 21:06, 30 June 2023 (UTC)
:::::sorry, you are correct. in original code i had the error handling in first hunk, and decided it looks better when the first hunk is success, but forgot to remove the "not"... doing it now (the name of the "success variable is a strong hint that true means success and false means error).
:::::peace. קיפודנחש (aka kipod) (talk) 22:43, 30 June 2023 (UTC)
Unexpected result when setting table value to nil
Consider the following code (from Module:Sandbox/MSGJ):
function p.main(frame)
args = frame.args
args.category = nil
return args.category
end
What would you expect from
: I would expect that it returns "Foo"; the frame.args object uses a custom metatable that handles gets so the value overwrite is ignored. * Pppery * it has begun... 14:24, 6 July 2023 (UTC)
::I can overwrite it to other values. Why is nil different? And is there any method I can set it to nil? — Martin (MSGJ · talk) 14:25, 6 July 2023 (UTC)
::: You can't overwrite to nil because the aforementioned metatable is based on the __index
metamethod, which, per the documentation, {{tq|is used when a table access t[key] would return nil}}. I don't know of any way around this, although if you were to use Module:Arguments instead of reading directly from frame.args then that handles setting nil properly. * Pppery * it has begun... 14:33, 6 July 2023 (UTC)
:::: You can copy the table with a for k, v in pairs( args) do
loop. Then you can set the values to nil. — Jts1882 | talk 14:54, 6 July 2023 (UTC)
:I don't know what to expect because I gave up trying to understand how args works (with or without Module:Arguments) for anything other than a read-only table. Spelling out Pppery's reply, args.category = nil
actually removes args.category
from args so when return args.category
is executed, the value does not exist in the table and that causes the __index function attached to args to be called, and that reads the underlying value ('Foo') from the wikitext. The generic method for manipulating frame.args is to clone args and adjust it as wanted, then use the clone with newChild
and pass the result to whatever is needed. There may be a way of avoiding that complex workaround in whatever the use case is. Johnuniq (talk) 04:13, 7 July 2023 (UTC)
::I also personally try to treat frame.args as read-only, even if you can overwrite it (with things other than nil). It's more in keeping with the functional ethos of minimizing mutation and avoiding what is often treated as global state in many of our modules. As alternatives indeed, either you can clone the whole table and then mutate the resultant, or you can create your own variables that take on relevant values. I prefer this second option myself because this also allows you to give the variables nicer names than what are often abbreviations and smushed words and duplicate parameter names in the template interface. Izno (talk) 04:53, 8 July 2023 (UTC)
Thanks everyone. This created a bug in my code which I found really hard to find! Basically I am calling a module which has nearly the same set of arguments, so for convenience I just passed the whole table of arguments from the calling module. But it turns out one argument ("category") was conflicting as the other module was using this for a different purpose. So I thought I would just set that one to nil before sending the table but that didn't work either. So I am now doing as recommended and constructing a new table of arguments for the other module. — Martin (MSGJ · talk) 10:53, 9 July 2023 (UTC)
Testing the new Module:Params
I wrote a new general-purpose module, Module:Params, somewhat similar to Module:TemplatePar but more flexible and powerful. The module is already being used by {{tl|Template journal}} and {{tl|Template journal inline}}. If you people have time I would like to ask to have a look at it, test it, collect ideas, help with the documentation, report bugs. --Grufo (talk) 01:17, 10 July 2023 (UTC)
: We already have too many modules in this area. We don't need even more ways to do the same thing. * Pppery * it has begun... 01:25, 10 July 2023 (UTC)
:: Hi Pppery, thank you for your early feedback. If I had known a module that did the same things I would not have written this new module. But the problem is that I did not know any other way to overcome the limitation of accepting maximum 50 parameters and drastically reduce the complexity {{Diff|Template:Template journal|1164566293|1151198388|like i did|diffonly=yes}} in {{tl|Template journal}} and {{tl|Template journal inline}}. I suggest you try and experiment with Module:Params, you might be pleased by its simplicity and the possibilities that it offers. --Grufo (talk) 01:33, 10 July 2023 (UTC)
Make changes to copied table element not reflect on old target elements of copying
I recently updated Module:Wikipedia ads/data. Part of the implementation fixes the {{code|id}} field of a table element ({{code|skippedEntries[i]}}) before copying it into the output tables (one of them is {{code|list[id]}}) when needed, multiple times. However, it has a problem. For some reason, after I've copied the first skippedEntries[i] with id 40, if I change the skippedEntries[i]'s id to another value, the old element with id 40 also turns its id into the updated id. How do I fix that? Aaron Liu (talk) 01:32, 16 July 2023 (UTC)
:I'm having trouble thinking at the moment so take what I say with caution. However, if you have a table t, and then execute a = t; b = t
, variables a and b refer to the same table. Executing a.id = 42
will also set b.id
to the same value. If you want different different tables in a and b, you have to use a = mw.clone(t)
and same for b. I would rearrange the code. I gather that Module:Wikipedia ads/list is loaded somewhere with mw.loadData. In that case (and if it's not used in another way), you can delete Module:Wikipedia ads/data and edit Module:Wikipedia ads/list to return the fixed table. Maybe that's a bit adventurous although quite achievable. If data is kept, I would edit it to construct the missing table rather than cloning it: t = {}; t.id = ...; t.image = ...;
and so on for the other fields, then insert t. Or just use clone. Johnuniq (talk) 03:46, 16 July 2023 (UTC)
::/data returns an additional table so I don't think I should do that. I'll try clone tomorrow. Aaron Liu (talk) 03:59, 16 July 2023 (UTC)
Producing a list
I have a template (Template:WPBannerDoc) which outputs an asterisk followed by text. When called with wikitext it produces an unordered list. I am trying to call this template from a module via frame:expandTemplate but the literal text is displayed without the list structure. Even prefixing
:Is this a case where you need to do something like
:—Trappist the monk (talk) 19:28, 20 July 2023 (UTC)
:At Template:WikiProject Medicine/sandbox#Parameters, the Parameters section at the bottom showed "*class – valid values are ... *importance – valid values are ..." where the asterisks were displayed. I think my edit at Module:WikiProject banner/templatepage/sandbox has resolved the issue. I inserted some newlines so asterisks were at the start of a physical line. I hope there are no bad side effects. Johnuniq (talk) 01:27, 21 July 2023 (UTC)
::Ah nice, thanks. I was using
'
Help with Russian module
Invoke detection
What is the easiest way for a module to detect if it has been called via #invoke or from a wrapper template? — Martin (MSGJ · talk) 16:46, 27 July 2023 (UTC)
:I believe the following works.
local function main(frame)
local result
if frame == mw.getCurrentFrame() then
result = "Module called via #invoke"
else
result = "Module called via require or debug console"
end
return result
end
return { main = main }
:Let me know if you confirm this works. Johnuniq (talk) 04:32, 28 July 2023 (UTC)
::Thanks. That is interesting, but does not answer my specific question which is about distinguishing between #invoke and wrapper template (which is also calling #invoke). I think what I want is to check if there is a parent frame or not. — Martin (MSGJ · talk) 20:57, 28 July 2023 (UTC)
:::Try frame:getParent():getTitle()
(if frame
is available) or mw.getCurrentFrame():getParent():getTitle()
(if not). Maybe something in the title would be helpful. Johnuniq (talk) 09:58, 30 July 2023 (UTC)
::::If I understand the question correctly, then this will throw an error if the module has been called via a direct invoke. The existence of a parent frame at all means there is a wrapper template, so you just need to check if Theknightwho (talk) 14:29, 31 July 2023 (UTC)mw.getCurrentFrame():getParent()
is not nil
. On a side note, it’s more reliable to check mw.getCurrentFrame()
instead of frame
unless you can guarantee that the frame object is actually the frame for the current page, which may not always be the case.
::::Ignore all of that - I forgot that the original frame has the module title, and the parent frame is the page with the #invoke:
on it. The actual solution is to check whether mw.getCurrentFrame():getParent():getTitle() == mw.title.getCurrentTitle().fullText
. This checks whether the title of the page with the #invoke:
(i.e. the parent frame) is the same as the title of the page being rendered (i.e. the current title). If there is no wrapper template, these will be the same. If there is one, they'll be different. Theknightwho (talk) 17:26, 31 July 2023 (UTC)
:::::Ummm... are you sure? I have used the value returned by mw.title.getCurrentTitle().namespace
as a way to limit categorization to article name-space only. That means that mw.title.getCurrentTitle().fullText
returns the name of the {{em|article}} that contains the #invoke:
whether #invoke:
is directly instanced in the article or hidden inside a template instance. If mw.title.getCurrentTitle()
returned a title object for the template that holds the #invoke:
, mw.title.getCurrentTitle().fullText
would return the name of the template; mw.title.getCurrentTitle().namespace
would always return the number for the Template namespace (it doesn't).
:::::—Trappist the monk (talk) 17:46, 31 July 2023 (UTC)
::::::@Trappist the monk - yes, that’s correct. mw.title.getCurrentTitle().fullText
is the page being rendered (usually an article). mw.getCurrentFrame():getParent():getTitle()
, on the other hand, is always the page with the #invoke
on it. If there is a wrapper template, these will be different; if there is no wrapper template, they will be the same. You need to compare the fullText
field of the current title object, because the title stored in the frame object is a literal string. Theknightwho (talk) 04:51, 1 August 2023 (UTC)
Maintain state between Module invocations
I originally posted Wikipedia:Help_desk#How_to_update_a_LUA_global_variable_between_multiple_Module_function_calls_from_a_wiki_page? about essentially maintaining the state of a global variable between multiple invocations of a Module from a single article page. The answer was that preserving the state of a global variable between multiple invocations is not possible. That in itself, begs the question, wouldn't it make LUA much more useful if it could preserve state within a wiki page? Is this limitation self-imposed by the Wiki infrastructure or cannot be done due to technical limitations in the Scribunto/Lua interface? Anyways, as an alternate solution, is there a way I can feed in multiple lines of data via Module parameters so I can maintain a counter that is used in formatting Module output? Or am I going to run into a Module parameters length limitation as some point?
For example:
RedWolf (talk) 18:09, 3 August 2023 (UTC){{#invoke:Sandbox/RedWolf|list|delim=/|mountains=
Mount Logan /m/5959/-1/Saint Elias Mountains/fa=1925/notes=Highest point in Canada/refs=First reference
Mount Robson/m/3954/2829/Rainbow Range/fa=1913/notes=Highest point in the Canadian Rockies
Mount Temple (Alberta){{!}}Mount Temple/m/3543/1544/Bow Range/fa=1894
}}
:You will probably run into post expansion transclusion limit with that approach. And also, that's not wikitext which is not friendly for users. Izno (talk) 18:19, 3 August 2023 (UTC)
:I haven't examined the above example but I have been told that it is a design decision that templates and modules have no state information. The idea is that different people should be able to simultaneously edit different sections of an article and preview/publish should not depend on other parts of the page. Johnuniq (talk) 23:26, 3 August 2023 (UTC)
Module:Mock title
- {{lmd|Mock title}}
I made a module for mocking Scribunto title objects. It can be used when testing code that uses title constructors like mw.title.new; normally the output of test code like this would depend on the state of the relevant wiki pages (and so people could break your tests by editing them), but by using mock titles you can make your tests independent of the state of the wiki. Please take a look at it and let me know if you have any feedback. — Mr. Stradivarius ♪ talk ♪ 13:47, 23 August 2023 (UTC)
Conversion of [[Template:Marriage]] to Lua
I checked the source for Template:Marriage and it keeps on using so much code and parser functions. I suggest that the conversion should make the template more workable. RMXY (talk) 05:18, 20 September 2023 (UTC)
:I agree that a conversion would make a lot of sense. Do you fancy learning lua? — Martin (MSGJ · talk) 07:08, 20 September 2023 (UTC)
::I want to learn how to do Lua. RMXY (talk) 08:25, 22 September 2023 (UTC)
: This is a solution in search of a problem. The template's quest for omniscience and built-in opinions should be pared back, rather than entrenching them by creating a module. * Pppery * it has begun... 14:22, 22 September 2023 (UTC)
::What do you mean by "built-in opinions"? I'm looking at it and not seeing a problem. Looks like a template that provides considerable utility. — SMcCandlish ☏ ¢ 😼 19:07, 22 September 2023 (UTC)
::: See Template talk:Marriage/Archive 8#Use of circa for an example of what I mean. I may well hold a minority opinion here, though. * Pppery * it has begun... 22:19, 22 September 2023 (UTC)
::::I see what you mean, but this seems like it should be reasonably easy to fix in the code, namely by no longer "helpfully" policing the input. At bare minimum, something like {{para|circa|y}} parameter could turn those checks off? — SMcCandlish ☏ ¢ 😼 22:34, 22 September 2023 (UTC)
::::: My point is that once you remove the input policing it will hopefully reach the point where it's no longer complicated enough to warrant a Lua module. * Pppery * it has begun... 00:05, 23 September 2023 (UTC)
Help with understanding Lua module
I'm very new to Lua and am trying to understand how Module:Settlement short description uses the contents of the infobox to automatically generate a short description for the page if one does not exist already. I can tell this is all done in the p.main() function through usage of p.shortdesc(), but I don't understand where frame comes from. It looks like it would contain the specific contents of the page. How can I provide the module with Wikipedia article titles, such as Morning Glory, Texas or Stoneham-et-Tewkesbury for example, to see how the text parameter provided to p.shortdesc() is built in p.main()? Then once I am able to do so, how can I view the contents of variable like subdivision_names or location within p.main? BaduFerreira (talk) 15:38, 27 September 2023 (UTC)
:The frame object contains all the parameters/arguments that is passed to the module. There are only really two frames you need to know about: frame.args
is a table of arguments from the template that calls #invoke, and frame:getParent().args
is a table of arguments passed by the page that called that template. This particular module only uses the latter. I'm not familiar with the code but I believe it is mainly using the parameters that are defined in Template:Infobox settlement. The actual title of the article is only used once, rather obliquely, with mw.title.getCurrentTitle().text
— Martin (MSGJ · talk) 20:29, 28 September 2023 (UTC)
::Okay, that makes sense. Thank you for the link, this looks like a very helpful resource. Is it possible to dump the table of arguments that any given page using this template passes to the module? I'd like to play around with the module and I think concentrating my efforts offline to a local copy would be more effective and less disruptive. BaduFerreira (talk) 22:10, 28 September 2023 (UTC)
:::frame
is interesting too.
:::
:::Results are available under the Lua logs dropdown in the Parser profiling data dropdown when you preview an article (or testcases page) that uses your module.
:::—Trappist the monk (talk) 22:55, 28 September 2023 (UTC)
::::What do you mean by results? Would that be the output of
:::::You edit the module and add the line somewhere in the function where frame is passed as an argument. Do not save the edit (you will finish by abandoning it, leaving the module unchanged). Underneath the edited module, find "Preview page with this template" and paste the title of a page where the module is used. Click Show preview to see how that page would look if the edit to the module were saved. Then the stuff at the bottom of the page should show the dump. Johnuniq (talk) 01:02, 29 September 2023 (UTC)
::::::Ah okay, I see. I didn't realize I could do that. I'm able to preview a page that uses Module:Settlement short description after adding the mw.dumpObject(frame.args)
function to p.main(), but I'm getting nil
as the output so I'll keep poking around. Thank you everyone for all the help so far! BaduFerreira (talk) 01:55, 29 September 2023 (UTC)
:::::::Sorry, it's mw.logObject(frame.args)
(log, not dump; dump gives a string). However, I just tried it (using Anah as the preview page) and the output is just table#1 { metatable = table#2 }
. That's because args is a magic table that doesn't do anything until you ask for a specific argument. You would need something like mw.logObject(frame:getParent().args.short_description)
but that outputs nil
because no parameters are passed to the template. Johnuniq (talk) 02:21, 29 September 2023 (UTC)
Compacting [[Template:Weather box]]
The syntax for Template:Weather box is unnecessarily verbose as each data entry receives its own row. I have no prior knowledge of Lua and am trying to condense the template:
Example: Template:New York City weatherbox would be condensed to something like this:
{{Compact weather box
|location = New York City
|source 1 = NOAA (relative humidity and sun 1961–1990; dew point 1965–1984){{cite web |url=https://w2.weather.gov/climate/xmacis.php?wfo=okx |title = NowData – NOAA Online Weather Data |publisher = National Oceanic and Atmospheric Administration |access-date = May 4, 2021}}{{cite web |archive-url=http://web.archive.org/web/20210504224841/https://www.ncei.noaa.gov/access/services/data/v1?dataset=normals-monthly-1991-2020&startDate=0001-01-01&endDate=9996-12-31&stations=USW00094728&format=pdf |archive-date=May 4, 2021 |url=https://www.ncei.noaa.gov/access/services/data/v1?dataset=normals-monthly-1991-2020&startDate=0001-01-01&endDate=9996-12-31&stations=USW00094728&format=pdf |publisher=National Oceanic and Atmospheric Administration |title=Summary of Monthly Normals 1991–2020 |access-date=May 4, 2021}}{{cite web|title=New York Central Park, NY Climate Normals 1961−1990|url=ftp://ftp.atdd.noaa.gov/pub/GCOS/WMO-Normals/TABLES/REG_IV/US/GROUP2/00305801.TXT|publisher=National Oceanic and Atmospheric Administration |access-date=July 18, 2020}}
|source 2 = Weather Atlas{{cite web |url=https://www.weather-us.com/en/new-york-usa/new-york-climate |title=New York, New York, USA - Monthly weather forecast and Climate data |publisher=Weather Atlas |access-date=July 4, 2019 }}
|units = imperial |preferred units = imperial
|temp color = default |precip color = green |snow color = blue |humidity color = blue
|record high |72 |78 |86 |96 |99 |101 |106 |104 |102 |94 |84 |75
|monthly high |60.4|60.7|70.3|82.9|88.5|92.1|95.7|93.4|89.0|79.7|70.7|62.9|97.0
|high |39.5|42.2|49.9|61.8|71.4|79.7|84.9|83.3|76.2|64.5|54.0|44.3
|mean |33.7|35.9|42.8|53.7|63.2|72.0|77.5|76.1|69.2|57.9|48.0|39.1
|low |27.9|29.5|35.8|45.5|55.0|64.4|70.1|68.9|62.3|51.4|42.0|33.8
|monthly low |9.8 |12.7|19.7|32.8|43.9|52.7|61.8|60.3|50.2|38.4|27.7|18.0|7.7
|record low |-6 |-15 |3 |12 |32 |44 |52 |50 |39 |28 |5 |-13
|precip |3.64|3.19|4.29|4.09|3.96|4.54|4.60|4.56|4.31|4.38|3.58|4.38
|snow |8.8 |10.1|5.0 |0.4 |0.0 |0.0 |0.0 |0.0 |0.0 |0.1 |0.5 |4.9
|precip day threshold = 0.01 in
|precip days |10.8|10.0|11.1|11.4|11.5|11.2|10.5|10.0|8.8 |9.5 |9.2 |11.4
|snowy day threshold = 0.1 in
|snowy days |3.7 |3.2 |2.0 |0.2 |0.0 |0.0 |0.0 |0.0 |0.0 |0.0 |0.2 |2.1
|humidity |61.5|60.2|58.5|55.3|62.7|65.2|64.2|66.0|67.8|65.6|64.6|64.1
|dew point |18.0|19.0|25.9|34.0|47.3|57.4|61.9|62.1|55.6|44.1|34.0|24.6
|sun |163 |163 |213 |226 |257 |257 |268 |268 |219 |211 |151 |139
|percent sun |54 |55 |57 |57 |57 |57 |59 |63 |59 |61 |51 |48
|uv |2 |3 |4 |6 |7 |8 |8 |8 |6 |4 |2 |1
}}
In addition to having only one row for each monthly statistic, rather than 12-13 rows, the suggested configuration would resemble a table, allowing better readability and editing of data. Unlike Template:Weather box/concise C and Template:Weather box/concise F, this template would support all the data provided in Template:Weather box. For the rows with 12 values rather than 13 (everything except monthly high and monthly low), the yearly value would be automatically calculated. Crossover1370 (talk | contribs) 19:12, 30 September 2023 (UTC)
:I agree that would be a better procedure and is something I thought about that while implementing Module:Weather box but it was already a bit over human comprehension. Some delimiter other than pipe would be used so each row could be parsed. Module:Football manager history does something similar in that it extracts fields from text rows. Another to-do item is to use mw.html to generate the table rather than wikitext. Johnuniq (talk) 23:36, 30 September 2023 (UTC)
::Would the comma be an acceptable delimiter? (as in |high = 40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44
)? Would there have to be quotation marks, as in |high = "40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44"
? I'm trying to develop this myself but I know nothing about Lua or how it is used in Wikipedia. Crossover1370 (talk | contribs) 01:13, 1 October 2023 (UTC)
:::I guess comma would never conflict with any of the parameters that weatherbox expects (if a value could ever contain a comma, you would want to pick a different delimiter). It might be ok to use spaces with a dash for missing items. Johnuniq (talk) 01:35, 1 October 2023 (UTC)
::::Would there have to be quotation marks at the beginning and the end of the sequence of values? As in: |high = "40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44"
? Or would |high = 40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44
(without quotes) be acceptable? Crossover1370 (talk | contribs) 01:55, 1 October 2023 (UTC)
:::::Quotes not needed. Everything in a template is a string (1.5 is three ASCII characters). Johnuniq (talk) 02:51, 1 October 2023 (UTC)
::::::Just use whitespace as delimiter instead of comma for even more readable template syntax: mw.text.split(datarow, '%s+')
Dexxor (talk) 08:17, 1 October 2023 (UTC)
JSON
Do we have a Lua module that can read a JSON table, something equivalent to Module:Data? I found Module:Jf-JSON but it looks way more complicated than I need. — Martin (MSGJ · talk) 11:33, 19 July 2023 (UTC)
:mw.loadJsonData, mw.text.jsonDecode, and mw.text.jsonEncode. mw.ext.data.get may also be relevant. Izno (talk) 16:25, 19 July 2023 (UTC)
::I'm thinking we could adapt Module:Data so that it can read JSON pages as well. There could be a parameter to switch between the modes or possibly it could be deduced using mw.title.contentModel — Martin (MSGJ · talk) 20:55, 19 July 2023 (UTC)
:::Do you want to access the data on the JSON page from Lua, or from a template? (From your later post, I'm guessing from a template.) To provide access from a template, if it's just one JSON page, you could create a simple wrapper module that calls mw.loadJsonData
on it, and returns the value from the call. This module can then be used as an argument to Module:Data. If the template is using a lot of data from the JSON page, converting the template to a Lua implementation may be worth considering. isaacl (talk) 17:58, 29 September 2023 (UTC)
::::A module which I could invoke in a template would be just fine. Could an additional function be added to Module:Data to call mw.loadJsonData and then pass to its main function? I'm not familiar with metatables so don't want to touch that module! — Martin (MSGJ · talk) 14:47, 4 October 2023 (UTC)
:::::In a kind of kludgy manner. The syntax Module:some module
on it, which means using Module:some module
as a key to the underlying table in the object, and treating the return value as a function. Since Module:Data can't hardcode functions for every single possible module that might be used with it, it sets up a metatable with an __index()
function that returns a function. This function uses the key value that was passed to __index()
as the name of the module page to access. The essential logic of this function could be extracted into a helper function, and the __index()
function could be modified to treat specific values differently: say, a key in the format of JSON:page name
could return a new utility function that calls mw.loadJsonData()
on the specified page and then passes its return value to the helper function. isaacl (talk) 16:43, 4 October 2023 (UTC)
::::::Not going to pretend I understood half of that! But if you would have time to sandbox some code I will gladly test it, and maybe other people would find this useful too — Martin (MSGJ · talk) 20:21, 4 October 2023 (UTC)
:::::::Module:Data doesn't have any test cases, so I'd have to first figure out its use cases and create tests in order to do regression testing. Thus unfortunately it's a bigger project than I'm looking to do at present. If you could describe your intended use case, maybe a simpler solution could be found. isaacl (talk) 02:06, 5 October 2023 (UTC)
::::::::My immediate needs were met by Module:Women in Green event (main function) which was certainly simple enough. Don't worry if you haven't got time, this is on my long-term wishlist. — Martin (MSGJ · talk) 08:00, 5 October 2023 (UTC)
Colon
I notice that string.upper(s)
is equivalent to s:upper()
- is that correct? Why is the "string" not needed in the second format? — Martin (MSGJ · talk) 13:28, 6 October 2023 (UTC)
:This is correct behaviour, and I believe is called a method call.
:If you call a function of an object using :
instead of .
, the first argument will automatically become the object the call was made from. For example, t:xyz(...)
is just an alternate way of typing t.xyz(t, ...)
:Since all strings have the string functions as methods (E.g. ("").upper
is string.upper
), this means s:upper()
is functionally acting as string.upper(s)
.
:You can see an example in {{slink|mw:Extension:Scribunto/Lua reference manual|Function calls}}. There's also some special rules when using :
to define a function, which you can read about at the bottom of [https://www.lua.org/manual/5.1/manual.html#2.5.9 this section] on the lua manual. Aidan9382 (talk) 13:59, 6 October 2023 (UTC)
::Thank you, that's helpful. I had no idea you could replace the word "string" with any string. Is that part documented somewhere? — Martin (MSGJ · talk) 20:54, 6 October 2023 (UTC)
:::This behavior is part of Lua but I forget where I saw it documented originally. Whether or not s:upper() works depends on what s is. It needs to be based on a table with a member called upper and that member has to be a function. Strings in Lua (but not mw.ustring) work like that. Johnuniq (talk) 23:06, 6 October 2023 (UTC)
::::The reason this logic applies to string objects is because their metatable's __index
is the string table.[https://www.lua.org/manual/5.1/manual.html#5.4 lua docs] This means attempting to index (access a member of) a string object will actually index the string table for that object. Aidan9382 (talk) 06:32, 7 October 2023 (UTC)
Module to sum table column
I am an absolute beginner in lua and wanted to develop a module Module:Sandbox/Miria~01 that automatically sums the values of the columns in a wiki table like this one created in my sandbox User:Miria~01/sandbox.
class="wikitable" style="text-align:center; font-size:70%;" | ||||||
Games
!Athletes ! scope="col" width:3em; font-weight:bold;"|Gold !scope="col" width:3em; font-weight:bold;"|Silver ! scope="col" width:3em; font-weight:bold;"|Bronze !scope="col" style="width:3em; font-weight:bold;"|Total !style="width:3em; font-weight:bold;"|Rank | ||||||
---|---|---|---|---|---|---|
align=left class="summerMedals"| {{GamesName|SOG|2008}} | 92 | 0 | 1 | 2 | 3 | 61 |
align=left class="summerMedals"| {{GamesName|SOG|2012}} | 116 | 1 | 1 | 2 | 4 | 43 |
align=left class="summerMedals"| {{GamesName|SOG|2016}} | 103 | 2 | 4 | 2 | 8 | 32 |
align=left class="summerMedals"| {{GamesName|SOG|2020}} | 87 | 3 | 1 | 5 | 9 | 28 |
align=left class="summerMedals"| {{GamesName|SOG|2024}} | colspan=6; rowspan=3| future events | |||||
align=left class="summerMedals"| {{GamesName|SOG|2028}} | ||||||
align=left class="summerMedals"| {{GamesName|SOG|2032}} | ||||||
colspan=2| Total | {{#invoke:Sandbox/Miria~01/sumMedals|calculateSum|summerMedals|All|{{FULLPAGENAME}}}} | 67 |
edited table on 11 September 2023 to show no error, original in the revision history [https://en.wikipedia.org/w/index.php?title=Wikipedia_talk:Lua&oldid=1174743806 Wikipedia_talk:Lua&oldid=1174743806]
last row (total) with invoke to load module:
!colspan=2| Total !! {{#invoke:Sandbox/Miria~01|calculateSum|Gold|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Silver|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Bronze|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Total|User:Miria~01/sandbox}} !! 67
However, only zeros are ever generated as a sum. I would be grateful for any small help.
local p = {}
function p.calculateSum(frame)
local args = frame.args
local column = args[1]
local wikitext = args[2]
local sum = 0
-- Iterate through the rows of the table
for row in mw.text.gsplit(wikitext, "\n") do
-- Check if the row contains the specified column
if mw.ustring.find(row, "|" .. column .. "|") then
-- Extract the value from the specified column
local value = mw.ustring.match(row, "||%s*([0-9]+)%s*||")
if value then
-- Attempt to convert the value to a number, or default to 0 if conversion fails
local numValue = tonumber(value)
if numValue then
sum = sum + numValue
end
end
end
end
return tostring(sum)
end
return p
Miria~01 (talk) 11:28, 10 September 2023 (UTC)
:{{reply|Miria~01}} It looks like you are trying to parse the contents of User:Miria~01/sandbox, but your code above instead tries to parse the literal string User:Miria~01/sandbox
as a wikitable. Instead you want to fetch the content of the page using title:getContent(). So instead of this:
local wikitext = args[2]
:You can do this:
local wikitext = mw.title.new(args[2]):getContent()
:Best — Mr. Stradivarius ♪ talk ♪ 11:43, 10 September 2023 (UTC)
::Thanks for the quick reply. The suggestion with title:getContent() obviously makes sense. Unfortunately only zeros are still generated. But I'll take a look at the module Module:USN fleet totals from User:Trappist the monk, how he did it, to hopefully find a solution for my issue. Miria~01 (talk) 12:56, 10 September 2023 (UTC)
:
:Not going to work as you want it to work because args[2]
is just the text string User:Miria~01/sandbox
.
:
:I wrote some code to render {{slink|List_of_current_ships_of_the_United_States_Navy#Fleet_totals}} by extracting the appropriate data from tables. See {{tlx|USN fleet totals}}, Module:USN fleet totals, and Module:USN fleet totals/data. You might want to look at that code to see how I did it.
:
:I can imagine difficulties in the future because editors have varying beliefs regarding how wikitext should be formatted. It might be best to have your module create the whole table from data stored in a module's subpage. There would be no parsing required for that.
:
:Seems odd to me that MediaWiki doesn't have Javascript to sum table contents. After all, MediaWiki does provide Javascript to sort columns so it would seem that they could also supply a script to sum columns and/or rows. That they don't suggests that there are difficulties that I am not aware of.
:—Trappist the monk (talk) 12:04, 10 September 2023 (UTC)
::Thanks for the suggestion, I'll definitely take a look at your modules and try to build on that with the previous save data in a module's subpage, summing the columns/rows in tables.
::I'm actually also surprised that, if at all, calculations can only be made on Wiki using {
::: The line if mw.ustring.find(row, "|" .. column .. "|") then
is searching for text "|Gold|" which never gets a result (hence sum=0). You want to find lines beginning with "|align=left|" or just "|" and then iterate the results of mw.ustring.match(row, "||%s*([0-9]+)%s*||")
. You need some way of deciding which column to extract or output all the sums in a single call. — Jts1882 | talk 14:01, 10 September 2023 (UTC)
::::Which all complexity is why I suggested building the table on the fly from data in a ~/data module...
::::—Trappist the monk (talk) 14:20, 10 September 2023 (UTC)
::::: Yes, data modules are much more flexible. I've used them before at Module:Goalscorers and Module:SportsRankings.
::::: In the meantime, I made a quick and dirty version of Module:Sandbox/Miria~01 that automatically sums the values of the columns Gold, Silver, Bronze and Total and outputs the sums for the table in User:Miria~01/sandbox. — Jts1882 | talk 14:58, 10 September 2023 (UTC)
:::::: All added a column option "All" to output the sums as four table cells in one module call. — Jts1882 | talk 15:07, 10 September 2023 (UTC)
:::::::Thank you very much, I had a wrong thought how to recognize the correct line with the value. Also realize that data-modules is actually the best and cleanest solution.
:::::::In the end, the driving force was that the total sum of medals in the medal tables of the individual nations (by Olympic event, by sports, etc.) at the Olympic Games (e.g. Russia_at_the_Olympics#Medal_tables) at the Olympic Games is correct. Since in the case of stripped medals (stripped after several years due to doping), individual users change accordingly the entry for the event, but neglect the total sum or change the entry for the year, but neglect to change it also at the sport itself and so incorrect numbers arise. Miria~01 (talk) 16:18, 10 September 2023 (UTC)
::::As a note, "align=left" is deprecated/obsolete HTML and is likely to be removed. In general, this whole endeavor is indeed brittle at best. Izno (talk) 16:24, 10 September 2023 (UTC)
::Just because I've not done much with the html library, this seemed like a useful learning opportunity so I have hacked Module:Sandbox/trappist the monk/html which creates a table along the lines of the table that Miria~01 posted in the OP. It ignores future events (I'm not sure that en.wiki looks favorably on stuff that has not yet occurred). The experiment relies on two tables; one for the all-time ranking (bottom right table cell) and one containing all of the necessary row data. To test it add this to a sandbox:
:::
::—Trappist the monk (talk) 16:46, 10 September 2023 (UTC)
Just for completeness: I created for my request in Module:Sandbox/Miria~01/sumMedals, that after specifying a targetClass as args[1], the type of medals should be searched for. e.g. for summer class="summerMedals" and for winter class="winterMedals". For the existing medal tables of all countries ("xxx"_at_the_olympics, e.g. Croatia at the Olympics) class="summerMedals" or class="winterMedals" would then have to be inserted into the table rows. At the same time, the infbox for the individual countries can also be updated directly on the same page
Miria~01 (talk) 11:44, 11 September 2023 (UTC)
@Miria~01 I think that I have finish playing around. My module at Module:Sandbox/trappist the monk/html and Module:Sandbox/trappist the monk/html/data renders summer and winter tables for Serbia and Mexico. Expanding to support other countries should mostly be a matter of clerical drudgery though no doubt, an awb script could be written to extract the pertinent data from articles using plain wikitext tables. The module also has an exported function to calculate total numbers of gold/silver/bronze medals for use in infoboxen. See this version of my sandbox for example renderings.
The modules should be sufficiently documented to make expansion and maintenance of ~/data relatively easy.
—Trappist the monk (talk) 16:42, 11 September 2023 (UTC)
Adding line to [[:Module:Interlinear]]
I want to add a parameter to {{tl|fs interlinear}} to allow for a right-to-left gloss for Semitic languages. I tinkered a little bit with the HTML that the template produces, and it seems like all that's needed to do this is change line #44 of :Module:Interlinear so that it can read float: right;
rather than float: left;
if a certain parameter (perhaps {{para|RTL|yes}}) is set. I asked the person who usually edits that template, but their last edit was in April so I don't think I'm hearing back on that anytime soon. Can someone here help me figure out how to make this alteration? Eievie (talk) 01:57, 19 October 2023 (UTC)
What links here
Up until just now Template:WikiProject Cephalopods invoked Module:WikiProject banner with a parameter containing a template, i.e.
|HOOK_ASSESS = {{WPBannerMeta/hooks/bchecklist}}
Template:WikiProject Cephalopods was not listed at Special:WhatLinksHere/Template:WPBannerMeta/hooks/bchecklist, however, a page like Talk:Vampire squid which transcludes Template:WikiProject Cephalopods was listed in WhatLinksHere, which surprised me. Why was the page listed but not the template? — Martin (MSGJ · talk) 07:20, 10 November 2023 (UTC)
:The point of WhatLinksHere is so MediaWiki knows what pages need to be regenerated when a template or module is changed. The page Template:WikiProject Cephalopods did not contain anything that would change if the now deleted Template:WPBannerMeta/hooks/bchecklist were changed. However, Talk:Vampire squid transcluded {{tl|WikiProject Cephalopods}} and its wikitext used to transclude {{tl|WPBannerMeta/hooks/bchecklist}}, so Talk:Vampire squid needed to be regenerated when Template:WPBannerMeta/hooks/bchecklist changed. In conclusion, the WhatLinksHere feature is not very helpful for those maintaining templates/modules. Johnuniq (talk) 07:59, 10 November 2023 (UTC)
::This is the reason I quite regularly do insource searches when messing around with templates. This has the problem of not detecting redirects, but it is definitely useful in some circumstances. --Trialpears (talk) 08:28, 10 November 2023 (UTC)
Regex question
I am using
to find valid parameters in a template's code. It is not working quite right.
For example the code contains
but it seems to be matching with
but not the
which I require. — Martin (MSGJ · talk) 13:00, 11 January 2024 (UTC)
:[^|]+
will go as far as it can to capture text before running into a pipe, which is why the first capture is so long and contains text from both event and event-type. gmatch then continues from the pipe it got stopped at last time so won't pick event-type up since its beyond it at this point. I'd recommend adding }
inside of that negated list, which should prevent it from over-capturing event (and therefore pick up event-type afterwards too). Aidan9382 (talk) 13:31, 11 January 2024 (UTC)
:: I'm guessing here, but try "-" instead of "+" in the capture. You could also try escaping characters that might have another meaning (e.g.{ and | which would need escaping in regex proper). — Jts1882 | talk 13:36, 11 January 2024 (UTC)
::: For some reason I didn't get an edit warning message and missed the reply above. — Jts1882 | talk 13:38, 11 January 2024 (UTC)
:::Apparently - is an alias for *. That would not help here — Martin (MSGJ · talk) 14:06, 11 January 2024 (UTC)
::Perfect, thanks! — Martin (MSGJ · talk) 14:03, 11 January 2024 (UTC)
:
:Another alternative might be to gmatch
the whole parameter and then parse that. In the debug console I get these results using string.match()
in place of string.gmatch()
:
::event
– this would be the first string.match()
result
::event-type|edit-a-thon
– and this would be the second string.match()
result
:—Trappist the monk (talk) 14:39, 11 January 2024 (UTC)
::Beware that the parameter default often contains braces in a nested parameter, magic word or template call, e.g.
How to make multilangual parameters in [[Module:Navbox]]
Hello!
I'm translated Navbox module into Kazakh Wikipedia, but have one issue. We've already have a :kk:Module:Navbox, but I want to upgrade it. Additionally in the some templates we also used English version of Navbox (english parameters). So I need to add english versions of parameters (Aliases?) to new :kk:Module:Шолғы exactly to :kk:Module:Шолғы/configuration. I've already ask this question on talk page of Module:Navbox, but nobody replied, that's why I'm writing here Thanks--Amangeldi Mukhamejan (talk) 15:15, 27 October 2023 (UTC)
:@Amangeldi Mukhamejan: i only saw this now, sorry about that. i hope it's not too late.
:a while ago i wrote a utility module that enables you to use any module from another language with localized parameter names. the idea is simple - i'm sure you won't have any trouble grasping it and figuring out how it's done. see :he:יחידה:תרגום יחידה
:in a nutshell: for each module you want "translated", you create a "translation" module (in retrospect i guess it could have been a JSON rather than module). then you call the utility module, passing it the target module, the target function, the name of the "translation module", and any parameter you want to pass directly.
:the utility module clones the frame (such that the "parent" of the clone is the real parent, not the utility module), it then enriches the "args" and the parent's args with the translated parameters, and then it calls the target module/function with this enriched frame.
:note that i said "enriches", not "replace". this means that the caller can use either the original param name _or_ the translated name, which i think is part of your requirements, you can mix and match - some of the parameters can be the translated ones and others can be the original ones
:there is some rudimentary documentation as a comment at the top of the module (the doc is not very long, but it's still 50% of the whole thing - the code is short and sweet and pretty easy to understand - no magic. i wrote it per some request on hewiki, and tested it to verify it works, but eventually the requestor decided not to use it, so you can say it's not "tried and tested", only "tested"...
:this of course is not specific to "navbox": once you install it, you can use it for any module, at the cost of creating "translation module" for each imported module you want to use with native language parameter names.
:if you do decide to use it, i'll be grateful if you can let me know, and of course, if you find bugs let me know too.
:peace. קיפודנחש (aka kipod) (talk) 04:24, 26 January 2024 (UTC)
Escape character
I have a string with a "#" character. When I use the string it produces a numbered list, but I just want to use it as a string. I have tried mw.text.nowiki
without success. I have also tried using \u0023
but it just converts it back to #. Any other suggestions? — Martin (MSGJ · talk) 12:01, 9 February 2024 (UTC)
:You can see the issue at the top of :Category:WikiProject Women in Red meetup 2017 articles. It is supposed to be producing :Category:WikiProject Women in Red #1day1woman articles but that link is not even working so perhaps it is impossible to have "#" in a page name? — Martin (MSGJ · talk) 12:01, 9 February 2024 (UTC)
::Seems to me the problem isn't that #
isn't escaped but that a line break is inserted before it where it shouldn't be. Nardog (talk) 12:09, 9 February 2024 (UTC)
:::Seems I just need to remove that character because the category name is not valid anyway — Martin (MSGJ · talk) 12:12, 9 February 2024 (UTC)
::::Oh, it's a hashtag, not a section link. Yeah, that's impossible. Nardog (talk) 12:16, 9 February 2024 (UTC)
::::Page names cannot contain # due to a MediaWiki restriction documented in Wikipedia:Page name#Technical restrictions and limitations. # is reserved for dividing the page name from a following anchor (typically a section header), e.g. Wikipedia talk:Lua/Archive 12#Escape character. Certes (talk) 22:13, 9 February 2024 (UTC)
As Nardog pointed out above, Lua modules seem to return strings which begin with "#" in an unexpected way. Compare below. My sandbox module just returns the string '#1day1woman' and you can see it behaves differently — Martin (MSGJ · talk) 10:38, 10 February 2024 (UTC)
- a#1day1womanb - look no line break
- a{{#invoke:Sandbox/MSGJ|main}}b - working now
:This is probably the same issue as was experienced at {{slink|Template talk:R|Space before colon in pop-up}}, where the # gets interpreted as defining a list item since it was the start of the string returned by the module. You can use mw.text.nowiki or manually encode it depending on your circumstance to get it to display normally. Aidan9382 (talk) 11:46, 10 February 2024 (UTC)
::Thanks Aidan, yes that works as expected — Martin (MSGJ · talk) 14:24, 10 February 2024 (UTC)
A new template parser
Hi - I mostly do work on Wiktionary, but wondered if anyone had a use for a powerful recursive backtracking template parser which I've put together, which is designed to scrape large amounts of template data from pages very quickly: wikt:Module:template parser. It's (very loosely) based on [https://pypi.org/project/mwparserfromhell/ mwparserfromhell], and builds a node tree of objects on the page that can then be traversed in order to retrieve data. The two available functions are described in the module, but - in short - parseTemplate
is a function that you feed a rawstring template into, and it'll return the template name and arguments, while findTemplates
is an iterator that returns data about each template it finds in the input text. Some features:
- It can handle arbitrary nesting of templates (
), arguments ({{ }}
), headings, wikilinks, HTML comments, parser tags and include tags, and has been designed to be as accurate to the native PHP parser as possible. This includes replicating some of the bugs in the native parser, to ensure full consistency. With one caveat (see below), I haven't yet been able to find a testcase it fails, even with really extreme or bizarre inputs.{{{ }}} - HTML comments and the
<noinclude>
,<includeonly>
and<onlyinclude>
tags are all handled correctly. By default, it assumes that the input text should be treated as transcluded, for the purpose of the include tags. This can be changed with a parameter. - It's extremely fast and lightweight for what it is: e.g. wikt:人 scrapes data from hundreds of other pages to retrieve Chinese transliterations, which requires calling this module every time. By far the biggest drain on resources in that is the unavoidable time taken by
mw.title
's:getContent()
method, not the parsing itself (which can be seen in the parse profile on that page). - The caveat is that it doesn't (yet) have special handling for parser tags like
<ref>
. It knows that they're there, but it doesn't yet know the various special ways that each one needs to be handled. In some cases this is very straightforward (e.g.<nowiki>
) and in some cases not (e.g.<gallery>
), so support for these will take some time. At the moment, anything between such tags is treated as raw text (i.e. as though it were in nowiki tags).
I'm reasonably confident it's the most powerful wiki markup parser that has yet been written in Lua (though I'm happy to be proven wrong!). Do let me know if you think this could come in handy for anything, and I'm happy to help in designing any implementations.
Theknightwho (talk) 16:21, 13 February 2024 (UTC)
Need help with edge case in my Lua Module
I wanted to port the following templates over to the Afrikaans Wikipedia: Template:Millenniumbox, Template:Centurybox, Template:Decadebox.
After an initial look at how they worked, I was overwhelmed by the sheer amount of nested templates that were used by these templates. I decided to instead copy the look of the templates, but to use Lua Modules instead for the backend logic.
Porting Template:Millenniumbox and Template:Centurybox over to Afrikaans Wikipedia using Lua Modules was easy enough for me and I am happy with the results.
However I am stuck on porting Template:Decadebox. This template has 2 edge cases which do not exist in the Millenniumbox or Centurybox. There is no 0th millennium nor 0th Century. However there is a 0th Decade and 0th Decade BC. See 0s and 0s BC.
I was aware of these edge cases when I was writing my Lua Module, but still the output does not work as I expect.
Here is my ported template :af:Sjabloon:Dekadeboks, and here is the Lua Module that it uses : :af:Module:Dekadeboks. On the template page documentation, you can see my different "test cases" All the examples work as expected except for my 2 edge cases.
The problem seems to be caused by the Lua not being statically typed.
I am passing the selected decade as an argument. For the 0s the argument value is "0" and for the 0s BC it is "-1".
Most of my calculations read the argument to the function as a number, but for this edge case, I read it as a string instead. So that I can handle "-0" as an argument.
I know it is kinda hacky, but I can't think of a better way to do it. Furthermore when I run my functions in an external IDE, or pass it to a local Lua interpreter, the function behaves as I expect.
For the simplest example see my function to get the category for birth years: "kry_geboortes_kat_str" it is at the very end of the module. Also see my function to get the category for deaths: "kry_sterf_kat_str" which is a slightly different approach, but also doesn't work.
Please can anyone advise how I could get these functions to correctly handle "0" and "-0" as an argument? Am I missing something here?
I would greatly appreciate any feedback/advice on this issue. - Rooiratel (talk) 09:43, 13 February 2024 (UTC)
:I think the 0s should be the first decade. That would resolve the hacky "-0" — Martin (MSGJ · talk) 10:41, 13 February 2024 (UTC)
::That is an idea, and it does make sense in that the 0s is technically the 1st decade AD. But if I went with this method, I would have to rewrite the entire module completely. I also think it will be more confusing for users. The enwiki template also uses 0 as an argument for the page on 0s. But I will definitely consider this approach as a last resort. But I didn't actually notice that I was doing this template different from the others, so I will definitely update the docs to explicitly state what it expects the arguments to be, and what they represent (whichever solution I go with). - Rooiratel (talk) 07:29, 14 February 2024 (UTC)
:It would better if you gave a couple of precise examples and say what the input is, what the output is, and what is wanted. It's not clear to me what the testcases show so please spell it out. I don't want to spend too much time at the moment so I'll just mention some points. Are you aware that -0 is equal to zero and is not negative? At line 230, num will be -0 if args[1] is '-0'. You can use tostring on negative zero and the first character will be a dash if the number was -0 (I see that line 238 covers that). Assuming you are using a normal frame and not something created artificially, frame.args[1] can only be a string (or nil if there is no args[1]). But any argument that exists can only be a string so tostring at line 229 won't help. I'll be away for many hours but will look again if the issue hasn't been resolved. Johnuniq (talk) 10:52, 13 February 2024 (UTC)
::> It would better if you gave a couple of precise examples and say what the input is, what the output is, and what is wanted.
::Apologies, I thought the template doc page was enough to give examples of the input and output. I do realize that it was not very clear on what the expected output should be.
::> Are you aware that -0 is equal to zero and is not negative?
::Yes, which is why I was attempting to use the tostring() method to handle it as a string instead of a number. I am using the "dek" variable for the string representation and "num" for the numeric representation.
::> But any argument that exists can only be a string so tostring at line 229 won't help.
::I thought as much, but in that case it is "converting" a string to a string, so it should still work as I expect.
::My main problem at the moment is not the specific output, but I am trying to hit a conditional-block when the dek variable is equal to "0" or "-0", but the function never seems to reach it.
::So essentially I need is: a function that takes a single argument which it stores in one variable as a string, and another variable as a number.
::If the number variable is greater than 0 then execute a block of code.
::If the number variable is less than 0 then execute a block of code.
::Else if the string variable equals "0" then execute a block of code.
::Else if the string variable equals "-0" then execute a block of code.
::I am not able to get these last 2 conditions to execute.
::I have added a very simplified test function which just returns a string saying which conditional block it reached. If you could please assist with that I would be very grateful. On my template page at the very bottom you can see the outputs, for my last 2 cases above those code blocks never execute. - Rooiratel (talk) 07:48, 14 February 2024 (UTC)
:::{{ping|Rooiratel}} The problems is that :af:Template:Dekadeboks#Test Function used to show "Reached else block" for the last two cases. In the last case, the parameter is "-0*" where I have written an asterisk where there is actually a space. It is an unnumbered parameter so MediaWiki does not trim the leading/trailing whitespace. You need code to remove the spaces which I did in an edit at :af:Module:Dekadeboks. Johnuniq (talk) 09:00, 14 February 2024 (UTC)
::::Thank you so much @Johnuniq! I knew it had to be something stupid like that. At least now I will never forget to trim out any whitespace from the arguments. I can apply the same fix to the rest of the functions, and it should resolve all outstanding issues I have with this Module. - Rooiratel (talk) 09:22, 14 February 2024 (UTC)
Template:Category disambiguation
Can {{t|category disambiguation}} be made to use Lua? There has to be a better way than using 50 conditionals. Thanks! HouseBlaster (talk · he/him) 22:49, 13 February 2024 (UTC)
:Templates are not converted to Lua simply because they are repetitious. They can be, but I don't think I would here. Izno (talk) 00:29, 14 February 2024 (UTC)
::@Izno If I'm honest, this seems like the perfect sort of template to convert to Lua, for three reasons:
::* It would massively reduce the amount of code, because it would be a simple loop. Repetitious code is a maintenance headache and annoying to edit.
::* There's no arbitrary upper limit to the number of arguments which can be passed into it (currently 100).
::* Tons of template calls like this is very slow by comparison, which can impact large pages.
::Theknightwho (talk) 14:29, 14 February 2024 (UTC)
::: Is anyone really going to want to disambiguate more than 50 different categories? Will there ever a time when {{tl|category disambiguation}} is not the only thing on the page, and thus it's performance on large pages matters? I don't think so. Given the average edit rate of one edit per two years I don't think maintainablility is an issue - more time is spent discussing and doing the conversion than will ever be saved by it having been done. * Pppery * it has begun... 14:49, 14 February 2024 (UTC)
:::These are all benefits of Lua in general. Do they aid this specific template? No, not really. There isn't anything complex about it such that the positive of the different language outweigh the negatives of the different language.
:::That said, given this feedback, maybe you should try converting it. Simple templates are the best ones to start with. Izno (talk) 18:10, 14 February 2024 (UTC)
::::You're replying to Theknightwho, author of one of the most complex Lua modules I have ever seen. I don't think they need simple templates to start with :) — Martin (MSGJ · talk) 21:17, 14 February 2024 (UTC)
::::: I think that comment was meant to be addressed to HouseBlaster, despite its indentation. * Pppery * it has begun... 21:43, 14 February 2024 (UTC)
::::::No, it was intended for Theknightwho, I just 1) didn't realize they were a different person from House, and 2) don't know everyone's credits. :) I'm not stopping anyone from converting anything to Lua if they want to take the time for it (WP:VOLUNTEER), I just am singularly convinced that this template doesn't need it for already stated reasons. But I am happy to redirect the suggestion to House. Izno (talk) 22:01, 14 February 2024 (UTC)
:::::::@Pppery @Izno You make good points, and I had only looked at the raw code when I made my earlier comment. That being said, I've done a sandboxed version at Module:Sandbox/Theknightwho/Category disambiguation, which is designed to replace the Cmbox call in the template, since this seemed relatively straightforward. The one difference is that throws an error if you supply fewer than four parameters (since that's the minimum to specify two categories), but that can easily be taken out. Theknightwho (talk) 01:14, 15 February 2024 (UTC)
Lua errors at ln:
ln: is a small wikipedia with less than 10 active users per month and non of them with lua knowledge. There are some lua errors in templates that were probably copy pasted in the past from fr:
The pages can be seen here: https://ln.wikipedia.org/w/index.php?title=Cat%C3%A9gorie:Pages_avec_des_erreurs_de_script&action=edit&redlink=1
Could someone who knows lua have a look to the templates ("modèle") and give us a hand or at least some advice? Thank you for helping. Bombo (talk) 21:35, 18 April 2024 (UTC)
: I've cleared all of the Lua errors from mainspace articles. Most of the template errors are due to the template being called but without parameters and will work on mainspace. * Pppery * it has begun... 23:14, 18 April 2024 (UTC)
Process template parameter in Lua before MediaWiki does its thing
{{moved from|Wikipedia:Village pump (technical) }}
I'm working on a module that let's the user to use some predefined placeholders to add categories/text. For example, on the "Category:144 births" category they can add the following template
{{YearCategory
|__DECADE__s births
|Births by year
|RD(__CENTURY__)-century births
|__YEAR__ beginnings
|header=In this category you can find people who were born on __YEAR__.
}}
And it will add the 140s births, Births by year, 2nd-century births and 144 beginnings categories to the page and will display a header with "In this category you can find people who were born on 144." content. The code is at :hy:Մոդուլ:ԺամանակիԿատեգորիա and an example of usage at :hy:Կատեգորիա:1944 ծնունդներ. It work fine except when I want to use those placeholders inside a template or an
:{{replyto|ԱշոտՏՆՂ}} Why not simply copy our Template:Birth year category header and its underlying modules? --Redrose64 🌹 (talk) 07:24, 21 April 2024 (UTC)
::The module I made works without typing the parameters and it is very generic, the same module can be used for :Category:Buildings and structures completed in the 1850s and it adds all the necessary categories (e.g. Buildings and structures completed in the 19th century, 1850s establishments1850s works, 1850s architecture, Buildings and structures by decade of completion). Basically, as long as the category title contains a year/decade/century, the module will work and will create the navigation box too, see :hy:Կատեգորիա:1990-ականների կառուցումն ավարտված շենքեր և կառույցներ as an example. The only thing I can't do with this is using wikitext logic inside the header. For example, I can't write
:::ԱշոտՏՆՂ, I assume you'd need to wrap it in nowiki tags and then unstrip it in the module, to stop the wikitext being processed. — Qwerfjkltalk 11:19, 21 April 2024 (UTC)
::::For example, Module:Demo does it, as can be seen in function get
. —andrybak (talk) 01:05, 22 April 2024 (UTC)
:An alternative approach is to use nested templates, e.g. {{((}}YearCategory|{{tlx|Decade|2024}} births..
to implement the decade handling. You may need {{((}}PAGENAME{{))}} or something derived from it as the template parameter. Certes (talk) 09:34, 22 April 2024 (UTC)
::... which is done by the {{tl|Title year}} family of templates, heavily used in the {{c|Chronology category header templates}}.
::Sometimes this is done in two steps to avoid extra calculations. For example, Template:Sport clubs (dis)established in YYYY category header and Template:Sport clubs (dis)established in YYYY category header/core. The "core" template does include a conversion from {{param|year}} to a decade using {{Tlx|DECADE}}. —andrybak (talk) 15:44, 22 April 2024 (UTC)
"too many expensive function calls"
I wrote the following function:
local function linkToWikipage(link, text)
local page = mw.title.new(link)
if page.exists == true then
if page.redirectTarget then
local redir = page.redirectTarget.fullText
or page.redirectTarget.prefixedText
return "" .. text .. ""
else
return "" .. text .. ""
end
else
return text
end
end
It works on a small scale, but on a larger scale I'm told {{error|too many expensive function calls}}. Can anyone help me find something cheaper that still fulfills the goals of:
- If the page exists, link to that. If the page doesn't exist, don't link to anything.
- If the page is a redirect, link to the redirect target.
Eievie (talk) 03:35, 23 April 2024 (UTC)
:It can't be done. Each check requires a page to be examined and that is expensive. MediaWiki protects itself from denial-of-service attacks and other bad ideas that would affect performance. A workaround, if really necessary, would be to have a bot periodically do the checking and update the page of links but that won't be suitable for many cases. Johnuniq (talk) 04:44, 23 April 2024 (UTC)
::This doesn't ping the same response, though. What makes it different?
::
::Eievie (talk) 05:44, 23 April 2024 (UTC)
:::Are you sure? HELP:ifexist (which {{tl|Link if exists}} uses) says it has the same limit of 500 although multiple checks of the same title are counted as one. Johnuniq (talk) 06:08, 23 April 2024 (UTC)
::::Yes, I'm sure it actually works that way in my testcases. I agree it conceptually seems odd, that's why I'm asking. Eievie (talk) 06:41, 23 April 2024 (UTC)
:::::I tried it at User:Johnuniq/sandbox2 and only 500 calls are allowed. Johnuniq (talk) 08:06, 23 April 2024 (UTC)
:Yeah, I had this issue at Module:ATP rankings and its related template, in that checking to see if every redirect existed was causing issues. We ended up hard-coding known outliers into a separate submodule and had the main module check that first before doing any sort of #ifexist. Primefac (talk) 11:16, 23 April 2024 (UTC)
::I'm doing this at Module:Unicode chart/sandbox. There are 2 types of links needed:
::* The header link
::** Don't need to check page existence (I'm pretty sure wikipedia has pages for all the blocks)
::** Need to link to the redirect target, so that the bolding feature works correctly (ie. if the template was being included on the page Greek and Coptic, the link would turn bold if the link said Greek and Coptic
but not if it said Greek and Coptic (Unicode block)
)
::* The unicode character links
::** Need to check of page exists (many characters do not have pages)
::** Linking to redirect target would be ideal, but isn't absolutely necessary
::Right now I'm using Module:Redirect for the former and {{txl|Link if exists}} for the latter. This does work (see testcases here). It creates the links I need and doesn't create a "too many expensive function calls" error.
::I just tried to create the above helper function to cover both, and I'm confused as to why that got that error when this doesn't. My understanding is that:
::* mw.title.new()
is the expensive part
::* once you've already done that, checking page.exists
and page.redirectTarget
are both cheap
::* Module:Redirect and {{txl|Link if exists}} both do the mw.title.new()
call
::So how is the above function more expensive than either {{txl|Link if exists}} and Module:Redirect? Eievie (talk) 16:14, 23 April 2024 (UTC)
:::No, creating a title object alone doesn't increase the expensive count, nor does redirectTarget. So you can check redirectTarget (which returns false if the page doesn't exist) before checking exists, which does increase it. Nardog (talk) 16:20, 23 April 2024 (UTC)
::::You're saying that page.exists
is the expensive part? So ordering the function this way would be cheaper?
::::
local function linkToWikipage(pageStr, text)
local pageObj = mw.title.new(pageStr)
if pageObj.redirectTarget then
local redir = pageObj.redirectTarget.fullText
or pageObj.redirectTarget.prefixedText
return "" .. text .. ""
elseif pageObj.exists == true then
return "" .. text .. ""
else
return text
end
end
::::I'm trying that now, and it's still creating {{error|Lua error: too many expensive function calls.}} Eievie (talk) 16:34, 23 April 2024 (UTC)
:::::Yes, that should at least reduce the expensive parser function count, even if it still exceeds the limit on a particular page. You can compare them in the parser profiling data at the bottom of the edit form. Nardog (talk) 16:50, 23 April 2024 (UTC)
::::::Ok, I figured it out: Calling the other templates, rather than calling the functions myself, just silences the error messages. Eievie (talk) 17:34, 23 April 2024 (UTC)
Discussion at [[MediaWiki talk:Scribunto-doc-page-header#Category:Module documentation pages]]
File:Symbol watching blue lashes high contrast.svg You are invited to join the discussion at MediaWiki talk:Scribunto-doc-page-header § Category:Module documentation pages. —andrybak (talk) 09:27, 14 May 2024 (UTC)
parsing the first sentence
Does anybody know a parsing method to reliably get the first sentence of an article on a Lua module, removing templates such as infoboxes completely? -1ctinus📝🗨 00:13, 3 June 2024 (UTC)
:Module:Excerpt is at least one or two users' attempt to date. Izno (talk) 02:23, 3 June 2024 (UTC)
:: Using
gets the first paragraph of the Lion article (minus infoboxes, templates, etc). Add {{para|links|no}} to get plain text. It should be straightforward to get the first sentence from that. — Jts1882 | talk 11:49, 3 June 2024 (UTC)
Editing the <code>args</code> metatable of a child frame
Module:Params offers the possibility to map or rename parameters using either helper templates or modules or parser functions. Currently, in the case of mapping_by_invoking
and renaming_by_invoking
, while iterating, a new child frame gets created for each parameter (#1, #2). This means that if the parameters to map or rename are more than about a hundred the code breaks, because, as the Scribunto-Lua manual says, “The number of frames that may be created at any one time is limited”.
I have tried to solve the problem in Module:Params/sandbox, but all my attempts at keeping only one child frame throughout the loop failed (#3, #4, #5, #6). The reason is that once the child frame object gets created I can no longer edit its .args
metatable. Yet, I would need to do that, because each module invocation needs to receive different parameters.
Testcases are available at Module:Params/testcases/tmaps and Module:Params/testcases/tmaps sandbox. Any idea on how to solve the problem and being able to map more than 100 parameters using a module? --Grufo (talk) 15:41, 3 June 2024 (UTC)
: Update. I have mentioned the problem at MediaWiki. --Grufo (talk) 12:09, 4 June 2024 (UTC)
Looking for an existing module that takes a page name and converts it into wikitext
Is there an existing Lua module like that either (a) takes a page name and converts it into wikitext or (b) takes a page name and regex and returns the result text (something similar to Module:String2#findpagetext)? Don't want to write a new module if one already exists and I thought something like this exists but I can't find it. Gonnym (talk) 09:20, 6 June 2024 (UTC)
: I am not sure I understood exactly what you are looking for, but for getting the wikitext of a page there is {{msgnw}}
– you should use the double colon if the page is in the main namespace, as in {{msgnw::Richard Feynman}}
. That text transcluded in this way can then be passed as a parameter to a template or a module (and this includes {{mfl|string|match}}, if that's what you are looking for). And so
::
: yields
::
: --Grufo (talk) 11:01, 6 June 2024 (UTC)
::I think that was what I was looking for, thanks! Gonnym (talk) 11:04, 6 June 2024 (UTC)
::: I am glad that helped! --Grufo (talk) 11:16, 6 June 2024 (UTC)
:Isn't "takes a page name and converts it into wikitext" just getContent
? Izno (talk) 15:58, 6 June 2024 (UTC)
::Yes, but I was asking how to access it from wikitext and not Lua. Gonnym (talk) 16:00, 6 June 2024 (UTC)
:::That sounds like transclusion: {{:Page name}}. Certes (talk) 17:12, 6 June 2024 (UTC)
::::Already solved above. Gonnym (talk) 17:56, 6 June 2024 (UTC)
Looking for module that processes black/white text.
Hi. I'm looking for a module that can output 000000 or FFFFFF depending on the color code inputted. Is one available? Thanks.
:How would the module decide which of the two colors to output? Izno (talk) 06:25, 11 June 2024 (UTC)
::I saw [https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color this post] on Stack Overflow. Could this be implemented in Lua?
:{{tl|Infobox television season}} uses
(simplified it), if this is can help you. Gonnym (talk) 09:36, 11 June 2024 (UTC)
::@Gonnym this should work, thanks!
Methods
If x is a string why can I use x:lower()
as a shortcut for string.lower(x)
but if y is a table then I can't use y:concat()
as a shortcut for table.concat(y)
? — Martin (MSGJ · talk) 13:01, 22 March 2024 (UTC)
:{{ping|MSGJ}} This is because string objects in Lua have a metatable where the __index
points to the the string
table in the standard library. Tables, by default, do not have a metatable (presumably as programmers often use custom metatables for tables in their programs). To unpack that explanation, you need to know how metatables work; there is a pretty good explanation in [https://www.lua.org/pil/13.html chapter 13] in the Programming in Lua book. Also there is a little bit more detailed treatment of the string library metatable [https://stigmax.gitbook.io/lua-guide/concepts/metatables here]. — Mr. Stradivarius ♪ talk ♪ 13:51, 22 March 2024 (UTC)
:: Does that mean if you use setmetatable(t, y)
you could then use t:concat()
? — Jts1882 | talk 14:29, 22 March 2024 (UTC)
:::Not unless t.concat
is a function.
:::t:concat()
is defined as t.concat(t)
.
:::For the latter to work, t.concat
has to be a function.
:::A working example:
t = { 'abc', 'def', 'z' }
y = { __index = { concat = function(x) return string.reverse(table.concat(x)) end } }
setmetatable(t, y)
z = t:concat() -- z = 'zfedcba'
:::Johnuniq (talk) 05:33, 23 March 2024 (UTC)
::::Thanks both for your replies. A lot to process there, but looks very useful/interesting. Is there an easy way to do the following:
::::* Associate a particular table with the standard table library
::::* Associate all tables by default with the standard table library
::::— Martin (MSGJ · talk) 09:34, 25 March 2024 (UTC)
:::::No, there is no good way to alter the way table
works. I recommend using standard table.concat
and living with it. However, it is possible to muck around with something like this for a single table.
t = { 'def', 'abc', 'A' }
mt = { __index = { concat = table.concat, sort = table.sort } }
setmetatable(t, mt)
a = t:concat() -- 'defabcA'
t:sort()
b = t:concat() -- 'Aabcdef'
:::::Search for Collection
at Module:Age to see how I have sometimes defined a simple list. It's very weird to follow but Module:IPblock has more examples includings :sort()
. Johnuniq (talk) 04:24, 26 March 2024 (UTC)
::::::That seems like it could be worth splitting off into its own module… jlwoodwa (talk) 07:18, 24 June 2024 (UTC)
Executing and scraping results from an advanced search url
Is a module capable of executing an WP:Advanced search via a url param that is passed to it, and then processing the output of the search? I would like to be able to pass this url to a Module, have it execute the search, and return the total number of results by scraping it out of the content. For example, it should return value 4
given this url:
: https://en.wikipedia.org/w/index.php?search=Draft%3A+hastemplate%3AOKA++hastemplate%3AAfC_submission%2Fdraft&title=Special:Search&profile=default&fulltext=1
The resulting Html contains the following which looks easily scrapable, if a module can access it:
:
The module should be capable of handling any url that represents an advanced search, and find the total results. Is that possible? Mathglot (talk) 07:04, 6 July 2024 (UTC)
:No. Searching uses Special:Search and modules cannot access special pages which are not based on wikitext. I don't know what API may be available for use by JavaScript. Johnuniq (talk) 08:01, 6 July 2024 (UTC)
:: Thanks. I suspected as much, but wasn't sure. I'll look into other avenues. Mathglot (talk) 08:06, 6 July 2024 (UTC)
Request for Lua code review: New language module
Reposting this village pump post for visibility: Wikipedia:Village_pump_(technical)#Request_for_Lua_code_review%3A_New_language_module
Feedback welcome on the talk page here.
--Nonabelian (talk) 15:27, 25 July 2024 (UTC)
Is there an expensive-parser-function-count counter?
{{Tracked|T177567}}
It would be very useful to know how much overhead remains at any given time during execution. ~ Tom.Reding (talk ⋅dgaf) 14:20, 10 August 2024 (UTC)
:Not that I know of. It is interesting that there is a function
:—Trappist the monk (talk) 14:48, 10 August 2024 (UTC)
:: There is the extremely ugly hack Module:Preview expense, but that's almost certainly not what you want. * Pppery * it has begun... 00:27, 11 August 2024 (UTC)
:If you are willing to look further than lua, there is parser_function_count.py in pywikipediabot which counts ALL parser functions. In theory, that could be changed to count expensive parser functions. Then you need another script to get all templates used on a page. That would result in a list of pages with their maximum possible expensive parser function counts. (some of those parser functions are guarded with if statements, which the script would not take account for) Snævar (talk) 09:01, 17 August 2024 (UTC)
::You could also do the same with getContent() in lua, with the same limitations. Snævar (talk) 09:03, 17 August 2024 (UTC)
:::Thanks, but I'm looking for something like mw.getExpensiveFunctionCount()
that I can easily query inside a lua loop to know when to break out of it. ~ Tom.Reding (talk ⋅dgaf) 10:41, 17 August 2024 (UTC)
Category detection (using new feature!)
After 11 years in Phabricator purgatory, T50175 has now been completed, and Lua can now detect the categories used on a page. Would someone be able to implement this at {{t|If in category}} to make it less expensive/less error-prone/substable? Sdkb talk 15:23, 16 August 2024 (UTC)
:Thanks for letting us know. Sounds as though it could be useful — Martin (MSGJ · talk) 16:29, 22 August 2024 (UTC)
Problem with escape character
This is from Module:Chessboard:
This is being identified as an error when you try to save it, but not exactly sure how to fix. — Martin (MSGJ · talk) 16:28, 22 August 2024 (UTC)
: Use % as the Lua escape character. — Jts1882 | talk 16:34, 22 August 2024 (UTC)
:
:Umm, pipe isn't a special character in lua patterns so does not need to be escaped. See mw:Extension:Scribunto/Lua_reference_manual#Patterns.
:—Trappist the monk (talk) 16:39, 22 August 2024 (UTC)
::If you look at the code in the module you will see
::Error: [243:31] invalid escape sequence near '\|'
::Perhaps it is the pipe which needs escaping — Martin (MSGJ · talk) 06:18, 23 August 2024 (UTC)
:::It seems the syntax highlighter is pointing out that the escape sequence doesn't make any sense (it's expecting something like \120
or \n
), but it's still legal code, and just gets interpreted as |
since a pipe has no special meaning when escaped. Aidan9382 (talk) 08:01, 23 August 2024 (UTC)
::::Is there anyway this can be coded which prevents the warning? At the moment you get a warning every time you try to save the page — Martin (MSGJ · talk) 08:04, 23 August 2024 (UTC)
:::::Just remove the \, since "\|" and "|" are the same in lua (e.g. try printing it). Aidan9382 (talk) 08:09, 23 August 2024 (UTC)
::::::That would render the gsub completely redundant/useless, so maybe this is not doing what it was supposed to do ... — Martin (MSGJ · talk) 08:19, 23 August 2024 (UTC)
::::::Have just realised that the function that contains this appears to be completely unused, and it is also not documented. So it is simplest if I just remove this function from the module and the error disappears — Martin (MSGJ · talk) 08:26, 23 August 2024 (UTC)
::::::Sorry Aidan, just noticed your edit to the sandbox. I had not noticed the extra space between the pipes, so that makes sense. If it turns out the function is being used, then I will put your version back in — Martin (MSGJ · talk) 08:30, 23 August 2024 (UTC)
::::: Did you try using %| as I suggested above? — Jts1882 | talk 08:27, 23 August 2024 (UTC)
::::::I think I did, but it doesn't make the syntax highlighter any happier — Martin (MSGJ · talk) 08:31, 23 August 2024 (UTC)
::::::: It gets rid of the error messages on the lines for me. — Jts1882 | talk 08:46, 23 August 2024 (UTC)
:(Lua patterns are not regex.) Izno (talk) 19:07, 22 August 2024 (UTC)
Legislationuk / Legislationlistuk
Module:Legislationuk is used by Template:Legislationuk is used by Template:Legislationlistuk List of acts of the Parliament of Northern Ireland does not fit into the module there are a couple aspects that I am not sure on how too change
The main thing i am struggling with is that the the regnal citations for uk acts last happened in 1962, so that's how it's been set up but the regnal citation for NI acts last happened in 1942. When I say "regnal citation" I mean, "10 & 11 Geo. 5. No. 1" or "14 Geo. 6. c. 1" or "13 & 14 Geo. 5. c. 7 (N.I.)".
The module uses data from Module:Legislationuk/data.
The citation happens at line 124, I think.
The pseudocode for the idea I am trying to implement is something like changing ``year > 1962`` to ``year > 1962 or (year > 1942 and jurisdiction = "northern ireland")``. DotCoder (talk) 00:57, 20 September 2024 (UTC)
:Mainly I just don't know how to adjust the module in the correct way to apply the citation system it uses for the NI acts properly. DotCoder (talk) 00:59, 20 September 2024 (UTC)
:
:Sorry, I'm not going anywhere near that mess. The author(s) couldn't be bothered to document the code (shame. shame. shame.), couldn't be bothered to use meaningful variable names, couldn't be bothered to organize all of that text in a data module.
:—Trappist the monk (talk) 14:40, 20 September 2024 (UTC)
::If it were documented, I wouldn't be asking for help. DotCoder (talk) 16:01, 20 September 2024 (UTC)
Request
Please help me in creating a page Module:Sandbox/பொதுஉதவி.
பொதுஉதவி (talk) 05:48, 1 November 2024 (UTC)
:I've gone ahead and made the page at Module:Sandbox/பொதுஉதவி. I assume the title blacklist was the only issue? Aidan9382 (talk) 08:33, 1 November 2024 (UTC)
Colours for dark mode
A module sets colours for table headings by using colour names such as 'white', 'black' or hex values for text, background and cell border. This is fine for normal skins but how should it be coded to say "use the inverse colour in dark mode"? Dark mode is picking up the names and using those as absolute, where I think what I want it to say is "unless colour is specified use skin defaults for text and background" (the default for border is 'none' so that's not a problem). Nthep (talk) 15:47, 28 October 2024 (UTC)
:Isn't styling something that could be / should be done with template styles css?
:—Trappist the monk (talk) 16:17, 28 October 2024 (UTC)
::if i understood template styles, quite possibly. Nthep (talk) 16:29, 28 October 2024 (UTC)
:This probably should have been asked on WP:VPT since it has nothing to do with modules.
:mw:Recommendations for night mode compatibility on Wikimedia wikis are the official recommendations from WMF about how to deal with dark mode consideration. The relevant section is this one.
:You can probably be assisted further by providing a specific template/module of interest where you are trying to be dark-mode conscious. Izno (talk) 17:59, 28 October 2024 (UTC)
::And I gather this is about Module:Rugby league match squad. While you can do something of the "if this isn't defined, use the basic colors", you still need to cover your bases when it is defined. Basically you have these options in that case:
::# Remove custom color support with its obvious downside. Branding is not that important, and that's almost exclusively the reason that a module like this uses color.
::# Apply [https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/hue-rotate hue-rotate] using a TemplateStyles sheet. This will result in the branding color being incorrect but the table will be dark rather than light.
::# Forcibly override any colors inserted using TemplateStyles and !important
while in dark mode. Anything using !important is usually considered to be technical debt, but at least your table is dark.
::# Live with light mode colors for both light and dark. Which preserves the branding information but makes someone using dark mode have to put goggles on. :)
::That's it. That's the story. You won't get everything you want all in one nice package. :( Izno (talk) 18:08, 28 October 2024 (UTC)
:::@Izno thanks. I'd go for #1 but as I seem to be in a minority about colours among rugby editors, I can see it being reverted. I'll see what I can work out about template styles (have to say that what there is on the subject here and on media wiki isn't very helpful) and look at #3. Nthep (talk) 09:03, 29 October 2024 (UTC)
:::@Izno Thanks again. I managed to adapt Module:Rugby league match squad/sandbox and it's calling template to use TemplateStyles ({{tl|Rugby league match squad/sandbox/styles.css}} which seems to work ok on my sandbox [https://en.m.wikipedia.org/w/index.php?title=User:Nthep/sandbox3].
:::I'm conscious that the module isn't the greatest piece of coding and is at serious risk of becoming an unitelligible mish-mash of code and styling. I see that TemplateStyles can be called from a module using frame:extensionTag
(mw:Help:TemplateStyles#How_can_Lua_modules_interact_with_styles?) and my thought is could all the styling could all be pulled out into TemplateStyles using function p.templateStyle( frame, src )
? Nthep (talk) 21:23, 5 November 2024 (UTC)
::::You can do something like this at the very end of main()
:
:::::
frame:extensionTag ('templatestyles', '', {src='Rugby league match squad/sandbox/styles.css'}),
return_t
});
::::—Trappist the monk (talk) 22:25, 5 November 2024 (UTC)
::::Yes, I would recommend placing the styles all in the sheet, at least those which can be. The above is the function call version, barring that I moved the TemplateStyles page just now. The object call version of it looks like extensionTag
). I normally just concatenate it like your general string, but of course you may need tostring the return item depending on what you're concatenating e.g.
:::::Thank you both for the replies, I will have a mess around and see where I get to. Doubtless I will be back with more questions. Nthep (talk) 10:52, 6 November 2024 (UTC)
Using #invoke in mainspace, as an alternative to templates
I've come across List of common misconceptions, which uses
instead of using {{tl|cite web}} (and other CS1 templates) directly. Is this a good idea, or discouraged? --YodinT 18:15, 17 November 2024 (UTC)
: It's a necessary evil when working with huge articles that would otherwise exceed the post-expand include size. Otherwise it's discouraged. * Pppery * it has begun... 18:18, 17 November 2024 (UTC)
Output unreadable with "2-ary truth table" template
File:"2-ary truth table" template produces hard to read text.png
As you can see, Template:2-ary_truth_table uses Lua whose output is unreadable with Wikipedia's "Vector (2022)" dark mode skin. Chai T. Rex (talk) 07:39, 26 November 2024 (UTC)
:@Chai T. Rex It already has a Wikipedia:TemplateStyles stylesheet, :Template:2-ary truth table/style.css, so it's a question of editing that to include some dark mode options. Is it just the text colour in the third column that's the issue? Nthep (talk) 13:38, 26 November 2024 (UTC)
::Yes, the third column is unreadable. Chai T. Rex (talk) 21:06, 26 November 2024 (UTC)
:::If there is no further help here, ask at WP:VPT what is needed in that css page. Johnuniq (talk) 01:32, 27 November 2024 (UTC)
Non-Latin assistance needed
Localization help needed for [[Module:Protection banner]]
{{Collapse top}}
{{col-begin}}{{col-break}}
class="wikitable sortable"
|+ {{nowrap|Aliases parameters}} | |
English | Korean |
---|---|
small | 작게 |
action | 동작 |
date | 날짜 |
user | 사용자 |
section | 단락 |
category | 분류 |
cateonly | 분류만 |
notice | 안내 |
{{col-break}}
class="wikitable sortable"
|+ {{nowrap|Aliases for {{para|action|value}}}} | |
English | Korean |
---|---|
edit | 편집 |
move | 이동 |
autoreview | 자동검토 |
upload | 업로드 |
{{col-break}}
class="wikitable sortable"
|+ {{nowrap|Aliases for {{para|reason|value}}}} | |
English | Korean |
---|---|
blp | 인물 |
dispute | 분쟁 |
dmca | dmca (identical) |
ecp | 중재위 |
mainpage | 대문 |
office | 재단 |
reset | 초기화 |
sock | 다중 |
template | 틀 |
vandalism | 훼손 |
dispute | 분쟁 |
{{col-end}}
{{collapse bottom}}
Hello, I want to import Module:Protection banner on kowiki. (We are still using old Template:Pp-meta) I want both English and Korean parameters and values to work for compatibility, but it seems that the module is a little bit complicated. I checked the modules in other languages, but they all used only English parameters and values. Is it possible to make an i18n table for aliases?--Namoroka (talk) 18:11, 24 January 2025 (UTC)
:you may want to look at :he:Module:תרגום יחידה. Basically it's a wrapper that accepts a module, function and a translation table names, and using the translation table invokes the function with a clone of original frame, augmented with translated params. For more details please read the documentation at the top. If i correctly understood your requirements, i think this module matches them to a T.
:Peace קיפודנחש (aka kipod) (talk) 15:51, 25 January 2025 (UTC)
::Thank you for your answer. I will take a look at the code you provided.--Namoroka (talk) 15:52, 25 January 2025 (UTC)
:::oh, i forgot the disclaimer: i wrote it and tested it, but as far as i know, it is not actually used in production - I'm not very good at promoting my work. I can't guarantee you'll be happy, but i stil give it at least 82.73% chance.
:::Peace קיפודנחש (aka kipod) (talk) 15:55, 25 January 2025 (UTC)
::::An 82.73% probability is good enough for me. lol --Namoroka (talk) 15:57, 25 January 2025 (UTC)
:::::oh, one more thing: if you do adopt it, please let me know - i haven't bothered to generate WD item for this module, but if it gets migrated to other wikis i should.
:::::Peace קיפודנחש (aka kipod) (talk) 16:20, 25 January 2025 (UTC)
::::::I checked your module, and while it can be used for translating other modules, it seems that it cannot be used for Module:Protection banner since the value also needs to be translated.--Namoroka (talk) 11:22, 27 January 2025 (UTC)
Completely AI generated script
Hi, I was working on a medal tally or table. after each row it needed to be shown the sum of total medal. It was very tricky using wikitext, but i tried my best. then i seek help from an AI chatBot. I have zero expertise on Lua, yet i tried to implement lua on my template. I don't know if it's ok or not. if someone could see Module:Sandbox/KEmel49 and see through human eye. My template test is ongoing on User:KEmel49/sandbox 6.––kemel49(connect)(contri) 00:49, 22 March 2025 (UTC)
:That is very good code. Spaces are used for indents instead of standard tabs, but the formatting, variable names, and logic are all perfect. The "local gold =" line is not quite correct. The "or 0
" should be outside the parentheses. As it is, if someone puts "x" or "-" for the number of gold, the module would crash when it tries to add gold (which is now nil). Same for silver and bronze. Rather than outputting "0", some may prefer an en dash but zero would be correct. I haven't fully studied the HTML but a quick look suggests it's good. Johnuniq (talk) 01:29, 22 March 2025 (UTC)
::@Johnuniq, Should i move that to Module:Medal tally?––kemel49(connect)(contri) 03:58, 22 March 2025 (UTC)
:::Probably. Later I could fix those points I mentioned. First, you might like to look around to see if there is already something to do this. Although that doesn't really matter because if there is, someone will eventually tell you. Johnuniq (talk) 05:03, 22 March 2025 (UTC)
Module calling Wikidata to list European parties' seats in various institutions
Hi,
Total newbie to Lua here (but happy to discover)! Here, I asked for help to make a template that would grab information from Wikidata (using the wikidata module and expressions using that module) based on two arguments (the name of the institution and the name of a party -- or some wildcards).
@Ahecht kindly responded with a proposal, but saying that the conditional structure I was looking for would be better achieved in Lua. Since this looked like a good opportunity to make something better and to learn, I thought I would come here and ask for support.
I won't recap the whole proposal here for the sake of brevity (but the above link should be clear enough, hopefully), but I welcome ideas and pointers! Thanks a lot in advance. Julius Schwarz (talk) 19:32, 17 March 2025 (UTC)
:Any ideas? Julius Schwarz (talk) 06:01, 21 March 2025 (UTC)
::Your code from the original thread would work. Lua is just written with the long form of if statements, so "else if", not "elif" like in python. Also, unlike python, you have to use the word "end" at the end of the if statement, it will not take into account the indentation like python does.
::You could just put your original code with some minor adjustment like that into a function, return the function, save it into the Module namespace and use it with