Wikipedia talk:Lua

From Wikipedia, the free encyclopedia
  (Redirected from Wikipedia:Lua requests)
Jump to: navigation, search
  WP:Lua
Project
  WT:Lua
Project talk
  Help
 
  To do
 
  Resources
en: m: mw: external
 

How mw.html.tag() works?[edit]

For example:

local tab = mw.html.create('table')
tab
    :addClass('wikitable')
    :tag('caption'):wikitext('something '):wikitext('and something')
    :tag('tr'):tag('td'):wikitext('a')
    :tag('tr'):tag('td'):wikitext('b')
return tab

Why it knows that I want to get:

<table class="wikitable">
 <caption>something and something</caption>
 <tr><td>a</td></tr>
 <tr><td>b</td></tr>
</table>

rather than:

<table class="wikitable">
 <caption>something and something
  <tr><td>a
    <tr><td>b</td></tr>
  </td></tr>
 </caption>
</table>

Where the :tag('caption') is closed?--A Sword in the Wind (talk | changes) 06:01, 15 October 2016 (UTC)

The Sribunto HTML library method mw.html.tag() doesn't perform any sort of "smart" closure of tags. The problem is that you accidentally misinterpreted the output of your code. When I run the code sample you provided I get the following output...
<table class="wikitable"><caption>something and something<tr><td>a<tr><td>b</td></tr></td></tr></caption></table>
...which is equivalent to...
<table class="wikitable">
	<caption>something and something
		<tr>
			<td>a
				<tr>
					<td>b</td>
				</tr>
			</td>
		</tr>
	</caption>
</table>
... which is the same as your "rather than" output. So, everything is working as expected. If you actually want code that outputs HTML equivalent to your first sample, you could do the following...
local tab = mw.html.create('table')
tab:addClass('wikitable')
tab:tag('caption'):wikitext('something '):wikitext('and something')
tab:tag('tr'):tag('td'):wikitext('a')
tab:tag('tr'):tag('td'):wikitext('b')
...which outputs...
<table class="wikitable"><caption>something and something</caption><tr><td>a</td></tr><tr><td>b</td></tr></table>
If it helps to show what is going on, the following code outputs the same HTML as the code immediately above:
local tab = mw.html.create('table')
tab:addClass('wikitable')
local caption = tab:tag('caption')
caption:wikitext('something ')
caption:wikitext('and something')
local tr1 = tab:tag('tr')
local td1 = tr1:tag('td')
td1:wikitext('a')
local tr2 = tab:tag('tr')
local td2 = tr2:tag('td')
td2:wikitext('b')
RP88 (talk) 09:44, 15 October 2016 (UTC)
If your first code box is what you're seeing in your browser, it's probably due to HTML Tidy fixing the broken HTML. SiBr4 (talk) 14:08, 16 October 2016 (UTC)
What does the code look like if you have a table nested with in the "tab" table in the example above? How do I create nested tables and ensure that all the tags get closed? Any examples would be greatly appreciated. Julialturner (talk) 07:03, 4 January 2017 (UTC)
@Julialturner: mw.html closes all of the tags automatically, so you don't have to worry about that. Creating nested tables is just like creating any other HTML structure with mw.html - if you put a <table> node inside another table's <td> node, then that's your job done. The part that usually confuses people is that every time you call :tag() mw.html returns a new node. This can have unexpected results if you don't know how it works. For example:
-- Example 1
local t1 = mw.html.create('table')
t1:tag('tr'):tag('td'):wikitext('foo') -- t1 points to the "table" node because we defined it on the line above.
mw.log(tostring(t1)) -- Logs "<table><tr><td>foo</td></tr></table>"

-- Example 2
local t2 = mw.html.create('table'):tag('tr'):tag('td'):wikitext('foo') -- t2 points to the "td" node, as that is the return value of the expression
mw.log(tostring(t2)) -- Logs "<td>foo</td>"
I'll explain this a little bit. Whenever we "chain" methods like this (e.g. foo:bar():baz()) the expressions are expanded from left to right. I find it easiest to visualise what's happening if I add more parentheses, like this: ( foo:bar() ):baz(). In effect, we are hoping that foo:bar() returns an object that has a "baz" method, and then attempting to call that method. Because of this, the overall return value of an expression with chained methods is the return value of the right-most method. Let me break down my example above.
mw.html.create('table') -- Returns a table node
	:tag('tr')          -- Calls the table node's "tag" method, and returns a new "tr" node
	:tag('td')          -- Calls the "tr" node's "tag" method, and returns a new "td" node
	:wikitext('foo')    -- Calls the "td" node's "wikitext" method, and returns the "td" node
The right-most method is the "wikitext" method of the "td" node, and as this returns the "td" node, that is the overall return value of the expression. The difference between example 1 and example 2 is that in example 1 we are not assigning the value of the expression to any variables, but in example 2 we are assigning it to the t2 variable. Hence in example 1, t1 points to the "table" node, but in example 2, t2 points to the "td" node. Now, as to how we make a nested table, first I'll give you an example.
local root = mw.html.create('table')
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the first row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the first row.')
			:done()
		:done()
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the second row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the second row. This cell has a nested table in it.')
			:tag('table')
				:tag('tr')
					:tag('td')
						:wikitext('The first cell of the first row of the nested table.')
						:done()
					:done()
				:done()
			:done()
		:done()
	:done()
Here we use the "done" methods to work our way back up to the original table element. You can avoid the final :done() calls if you make sure that root always refers to the original table element:
local root = mw.html.create('table')
root
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the first row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the first row.')
			:done()
		:done()
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the second row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the second row. This cell has a nested table in it.')
			:tag('table')
				:tag('tr')
					:tag('td')
						:wikitext('The first cell of the first row of the nested table.')
Or if you want to be able to access either table at any time, you can do something like this:
-- Make the root table and store a reference to it in the rootTable variable
local rootTable = mw.html.create('table')

-- Add a row to the root table
rootTable
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the first row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the first row.')

-- Add a second row to the root table, and make a reference to the nested table's "table" node
local nestedTable = rootTable
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the second row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the second row. This cell has a nested table in it.')
			:tag('table')

-- Add a row to the nested table.
nestedTable
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the first row of the nested table.')

-- Add a third row to the root table
rootTable
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the third row.')
			:done()
		:tag('td')
			:wikitext('The second cell of the third row.')

-- Add another row to the nested table
nestedTable
	:tag('tr')
		:tag('td')
			:wikitext('The first cell of the second row of the nested table.')
This has been a long post - hope it helps! — Mr. Stradivarius ♪ talk ♪ 13:33, 4 January 2017 (UTC)
@Strandivarius: Thank you so much for all the examples. I have done something like the first example of the nesting without really know what I was doing. It works most of the time, but it was brought to my attention that some of the end tags weren't produced in the raw html (Module:Infobox_gene). It renders correctly in wikipedia, but if you look at the html it is missing some end tags. I am in the process of looking for missing :done(), based on what you have told me here. — Preceding unsigned comment added by Julialturner (talkcontribs) 19:01, 4 January 2017 (UTC)
Fantastic post by Mr. S! When playing with mw.html I found it useful to dump (pretty print) the results. See Module:Dump#Dump of a formatted html string. It would be helpful if you could put some code in a sandbox that demonstrates the problem, with a dump. Johnuniq (talk) 23:58, 4 January 2017 (UTC)

<ref>...</ref> ?[edit]

Hi everyone! I'm trying to create an option in Module:Wd that adds references from Wikidata to claims from Wikidata. However, simply outputting a reference between the tags <ref>...</ref> from a module keeps these tags as plain text; they are not processed by Wikipedia. This differs from templates, where such output is actually processed and converted into a real reference.

Is there any way to add references from a module? Or am I condemned to using templates for this?

Thanks, thayts💬 13:10, 9 December 2016 (UTC)

Look at Module:Footnotes, particularly the return value from f.sfn().
Trappist the monk (talk) 13:16, 9 December 2016 (UTC)
You might wish to review Module:Video game wikidata and especially buildCite (which can probably be changed to include Module:Citation/CS1 directly via require()). That said, is there a reason you aren't e.g. working in Module:Wikidata/sandbox? We don't really need two general purpose Wikidata modules. --Izno (talk) 13:44, 9 December 2016 (UTC)
The technical reason that this does not work is that Lua doesn't do any preprocessing of module output. Arguments are preprocessed before they are passed to Lua, but unless you tell it otherwise, Lua just outputs regular strings. This is mostly for performance reasons, but also because (although it shouldn't in general) preprocessing things twice may cause some things to break. To preprocess things inside Lua, you need to use methods in the frame object. You could do it with frame:preprocess('<ref name="foo">bar</ref>'), but it is more efficient if you do it with frame:extensionTag{name = 'ref', content = 'bar', args = {name = 'foo'}}, as it avoids the overhead of the parser having to parse the HTML tags and preprocess whatever content you put inside them. — Mr. Stradivarius ♪ talk ♪ 01:10, 10 December 2016 (UTC)
Thank you all very much for the examples and explanation. I created this module because I wanted to provide an alternative that is more intuitive (still working on that) and more logical (why if I call a module called "Wikidata" must I supply "FETCH_WIKIDATA"... the problem that it's trying to address should be addressed one level higher), but mostly because I wanted to learn how to create a module and I found it a waste not to share it with those who might prefer to use it. Thanks, thayts💬 16:41, 10 December 2016 (UTC)
@Thayts: Sorry for the late reply, but I only just noticed your implied question, why if I call a module called "Wikidata" must I supply "FETCH_WIKIDATA"? The problem is that we only have permission to use Wikidata in infoboxes, and only then with the proviso that local data should take precedence. That means that there are three possible outcomes for a given field in an infobox: (1) the field displays with a value supplied locally; (2) the field displays with a value supplied from Wikidata; (3) the field does not display at all. The third outcome happens through the infobox logic whenever the parameter is empty or missing, and it may be that the parameter is explicitly set to be empty in an article to ensure that the field is not displayed. Given all that, how would you suggest the template logic should be arranged so that we can fetch the value from Wikidata without using a "special" value to trigger it? I couldn't see a simple way in 2013 when the module was originally written, so I settled for having a trigger value that wouldn't be at all likely as a locally supplied value. I'd be happy to hear your solution. --RexxS (talk) 03:17, 2 March 2017 (UTC)
@RexxS: I would come up with something like User:Thayts/sandbox/1 as included at User:Thayts/sandbox/2. I've added the "nowikidata" parameter to accommodate for outcome number 3 in case the parameter is missing. I suppose with your solution you would need a similar parameter (but then the opposite "fetchwikidata") because otherwise you wouldn't be able to fetch from Wikidata at all as you describe it. thayts💬 17:11, 4 March 2017 (UTC)
@Thayts: So your solution to catering for all three different options would be to use another parameter? You mean a bit like Module:WikidataIB does? Doesn't that make your criticism of the way Module:Wikidata works just a matter of your personal dislike of using a special value for a parameter, as opposed to having another parameter? Couldn't somebody equally complain "Why must I supply |nowikidata=true/false when I call the module"? If you don't like using a special parameter value in the way that Module:Wikidata does, you have a perfectly good alternative in Module:WikidataIB that also addresses the "opt-in" vs "opt-out" issues. --RexxS (talk) 21:37, 4 March 2017 (UTC)
@RexxS: Well, I don't see a particular benefit to the extra parameter and if it were up to me I would leave it out. It was just a way to accommodate for how you would like to have it (you do need something extra too anyway). I'm not trying to convince anyone here of what would be the best way, all I'm saying is that in my opinion a toggle whether to fetch from Wikidata or not should not be part of a module that is designed particularly for fetching from Wikidata. thayts💬 22:16, 4 March 2017 (UTC)
Well, unfortunately, as you can see from your own experiments, it is necessary to allow the template calling the module to toggle whether to fetch from Wikidata or not, in some way. Incorporating that logic into the module is far more efficient than hard-coding the testing into every separate infobox template that calls the module. --RexxS (talk) 22:38, 4 March 2017 (UTC)
@RexxS: Like I said, I see no benefit in the extra parameter and so neither in the toggle (in the particular case of infoboxes). Then where you would do something like {{#invoke:wikidata|{{{country|FETCH_WIKIDATA}}}}} I would do something like {{{country|{{#invoke:wd}}}}} and so there is no real difference (except that the latter doesn't do a superfluous call to a module). thayts💬 22:45, 4 March 2017 (UTC)
And if you'd really need to have a toggle at multiple places, then simply wrap the module inside a template that provides such a toggle and include that template instead. thayts💬 22:59, 4 March 2017 (UTC)
Of course there's a difference. We originally tried supplying the wikidata whenever there was no local parameter supplied as you suggest, but quickly found that editors insist on having control over whether a value from wikidata was fetched. See Template talk:Infobox book for specific problems, and see Wikipedia:Village pump (policy)/Archive 128 #RfC: Wikidata in infoboxes, opt-in or opt-out? and try to get a sense for the strength of feeling. Or look at Wikipedia:Wikidata/2017 State of affairs for an idea of how your suggestion would be received.
Why on earth would anybody write the toggle logic using parser functions and then wrap that around a Lua module that can do the same toggle a thousand times more efficiently? There's no use for the module without the toggle (we can only fetch Wikidata for use in infoboxes), so why wouldn't it be part of the module? --RexxS (talk) 23:14, 4 March 2017 (UTC)
I'm not suggesting anything. My module is just a building block. You can use it in any way you want. And that's all there is to it. thayts💬 23:41, 4 March 2017 (UTC)

Moving[edit]

I saw User talk:Peter coxhead#Testcases page in mainspace and tried to move it to Module space. However, when I tried I got "Non-Module pages cannot be moved to the Module namespace (except for /doc pages), and Module pages (except for /doc pages) cannot be moved out of the Module namespace." and it deletes the target page without letting you know what it has done. How do you move stuff over. I figure you could move it to a Module:something/doc and then to the correct title but I've done enough screwing around for now. CambridgeBayWeather, Uqaqtuq (talk), Sunasuttuq 03:43, 30 December 2016 (UTC)

@CambridgeBayWeather: It cannot be moved to the module namespace; however, it should not remain in mainspace since it is not an article. With the exception of /doc, all pages in the module namespace must be Scribunto, not wikitext. Module /testcases are written in Lua (Module:Autotaxobox/testcases), not wikitext. — JJMC89(T·C) 06:29, 30 December 2016 (UTC)
So how is it moved so as to keep the history intact? CambridgeBayWeather, Uqaqtuq (talk), Sunasuttuq 06:34, 30 December 2016 (UTC)
@CambridgeBayWeather: You move it with the usual "Move" link, just like with any other page. You just can't move it to the module namespace, as a) it's impossible and b) it wouldn't make sense, as it isn't a Lua module. Most test cases pages of the kind in question are kept in the Template namespace. There are some test cases in the Module talk namespace, but these are generally reserved for those generated from a test case module located in the Module namespace. — Mr. Stradivarius ♪ talk ♪ 10:01, 30 December 2016 (UTC)
Thanks. CambridgeBayWeather, Uqaqtuq (talk), Sunasuttuq 21:05, 30 December 2016 (UTC)

Can you test a Lua module out of your user space?[edit]

I've tested templates in my user space, by using {{User:TJRC/Sandbox/TemplateName}}. It looks like you can't do that with modules, i.e., with something like {{#invoke:User:TJRC/Sandbox/Modulename|func}}. Is this correct? I just want to check before I create something in Special:PrefixIndex/Module:Sandbox. TJRC (talk) 01:11, 7 January 2017 (UTC)

Modules must exist in the Module name space so you can sandbox your project in Module:Sandbox.
Trappist the monk (talk) 01:26, 7 January 2017 (UTC)
For an example, see Module:Sandbox/Johnuniq/testpre and edit its talk page to see how it calls the sandbox module. That page was originally set up to test what happens when a <pre> block is returned by a module, but I should have used a more generic name because I have used it for lots of small tests, mostly without saving anything. I write some code to test a point I'm working on, edit that page but don't bother saving. Instead, under "Preview page with this module" enter "Module talk:Sandbox/Johnuniq/testpre" for the Page title and click "Show preview". Of course if you are building a larger module you can save and muck around, but the the preview feature is very handy. Johnuniq (talk) 01:41, 7 January 2017 (UTC)
Thanks to both of you. That's what it looked like to me, but I wanted to be sure. TJRC (talk) 01:49, 8 January 2017 (UTC)
actually, it _is_ possible to test lua modules not from the module namespace, and use your user namespace instead.
this is a very poorly publicized, but beautiful feature of Special:TemplateSandbox. from there, you define a "prefix", such as "User:TJRC/Sandbox". once the prefix is defined, you create your "sandbox modules" and "sandbox templates" like so: User:TJRC/Sandbox/Module:testmodule and User:TJRC/Sandbox/Template:testmodule (_do not forget the colon!). now, when invoking {{#invoke:testmodule| bla | blabla }}, or when transcluding {{testtemplate | param ... }}, it will look first for pages under the prefix/Module: and prefix/Template:, and will use those when exist. this means you can test deeply nested stuff: let's say page a transcludes template b which in turn transcludes c and so on, and eventually, template Z invokes modules alfa, beta and gamma.
you can create sandbox doppelgangers for template Q (in the middle of the transclusion chain), and for modules beta and gamma, but _not_ alfa, and then "preview" page A from the Special:TemplateSandbox, and it will Do The Right Thing(tm).
disclaimer - it's been a few years since i _actually_ used this feature. i believe it still works.
HTH, peace - קיפודנחש (aka kipod) (talk) 22:49, 10 February 2017 (UTC)

Testing a template/a module that takes parameters from parent[edit]

Hi, I am wondering how I can test a module like module:labels that contains functions that doesn't take parameters but rather fetches the parameters from the parent scope - in this case a template instantiation. Can I use Module:UnitTests for this? Moberg (talk) 20:11, 21 February 2017 (UTC)

Unclear which module you mean, but you can use Template preview with any template or module. To do this make your changes to the module, then to test them enter the full name (so prefix any template with 'Template:') of the template or page it is used on in the box below, labeled "Preview page with this template" and click 'Show preview'. You should see that page, but with your modifications to the module (or template) used in place of any instances of it. This also works with the sandbox, to let you test changes there before committing them to the main module or template.--JohnBlackburnewordsdeeds 20:29, 21 February 2017 (UTC)
Sorry, definitely unclear. I mean this module: [1]. And about testing, what I mean was not previewing, but writing unittests with Module:ScribuntoUnit for example. Is that possible? Moberg (talk) 20:41, 21 February 2017 (UTC)
@Moberg: Could you say which specific functions you are talking about? Usually parameters from templates are fetched using frame.args, but I don't see that anywhere in the module. — Mr. Stradivarius ♪ talk ♪ 23:33, 21 February 2017 (UTC)
My guess is that testcases for wikt:Template:label are wanted, and that template ends up calling wikt:Module:labels/templates which uses wikt:Module:labels in a manner I have not investigated. Johnuniq (talk) 00:17, 22 February 2017 (UTC)
Yes I wanted to test the template because I'm not sure how I could test the module since it doesn't take any direct parameters. I wrote some tests at Swedish Wiktionary using UnitTests, but if possible I would like to try out Module:ScribuntoUnit Moberg (talk) 08:03, 22 February 2017 (UTC)

Lua request[edit]

Hey,
I was wondering if there is a way to find how many lines does a text contain.
for example:

a
b
c

would give 3
Thanks--Mikey641 (talk) 12:00, 22 February 2017 (UTC)

@Mikey641: Yes, you just need to count the newline characters in the text, then add one to get the number of lines. string.gsub has a count feature built in, so it's probably easiest to use that. This code should work:
local function countLines(s)
	local _, count = s:gsub('\n', '%0') -- Count newline characters in s
	return count + 1
end
Let me know if you have any questions about it. Hope this helps. — Mr. Stradivarius ♪ talk ♪ 14:40, 22 February 2017 (UTC):::
@Mr. Stradivarius:. Thank you. I have one question: I put the code in he:יחידה:מונה הופעות so how am I suppose to use it? as {{#invoke:מונה הופעות|countLines|WHAT PARAMETER??}} like what parameter is the string? thank you very much--Mikey641 (talk) 14:57, 22 February 2017 (UTC)
@Mikey641: The function as I wrote it above isn't accessible from wikitext - it's only accessible from other Lua functions in the same module. I've changed your module in this edit so that countlines can take arguments from wikitext. You can call it using {{#invoke:מונה הופעות|countlines|text goes here}} or {{#invoke:מונה הופעות|countlines|text=text goes here}}. Best — Mr. Stradivarius ♪ talk ♪ 23:27, 22 February 2017 (UTC)
thank you very much!!!--Mikey641 (talk) 06:12, 23 February 2017 (UTC)

Cached module expansion[edit]

Hi, in itwiki we were wondering if the expansion of a module is cached by the MediaWiki parser or not. Let's say page A includes ten times {{#invoke:B|main}}. Is the main function in module:B executed once or ten times? I would say "ten times", but I don't know parser internals. The module could contain randomly generated content or os.time(), so the parser can't cache it, or is it able to be aware of these functions? --Rotpunkt (talk) 16:11, 25 February 2017 (UTC)

Yes, module B is loaded and executed ten times. You can demonstrate that by the fact that some (sloppy IMHO) modules have pseudo-global variables at the top, like local count = 10 and functions then use and change count. However, count is always 10 when the module starts—nothing is shared between the separate calls to module B. The good news is that it is astonishingly fast. Module:Convert is breathtakingly enormous and complex yet well over 1000 {{convert}} calls can be executed on a single page.
If module B contains only read-only data, and if it is likely it may be used several times on a page, the module can be loaded into memory once, and the same copy will be used for each of the ten times it is called. That uses mw.loadData instead of require. Johnuniq (talk) 00:43, 26 February 2017 (UTC)
So, knowing that mw.loadData( module ) does not support functions, a module that does not use global variables actually it is not recognized as "functional", calling it only 1 time in the whole page. I'm right? --Valerio Bozzolan (talk) 04:01, 26 February 2017 (UTC)
I don't understand that. If a module contains only read-only data, it can be loaded with loadData. The first call on the page will load the module (and check that it contains only data). Subsequent calls on the same page will use the cached result from the first load. However, if a module is called via #invoke or require, a fresh copy of the module will be loaded each time the module is used. One way to think about it is to know that part of the design criteria for MediaWiki is that a snippet of wikitext should render to the same html output regardless of context. For example, something like {{example|one|two}} would give exactly the same result regardless of anything else on the page—it does not matter if the template being rendered is the first occurrence on the page or the tenth. MediaWiki is like that because the designers want section editing to work (say for preview) without having to process the whole page. Johnuniq (talk) 06:55, 26 February 2017 (UTC)
There are several steps to invoking a module:
  1. Load the source of the module from the wiki page.
  2. Load the module source into Lua, which produces an "init chunk" function in Lua.
  3. Execute the "init chunk" to actually create the functions.
  4. Execute the invoked function.
Steps 1 and 2 happen once per page. 3 and 4 need to happen each time the module is invoked, to prevent one invoke from affecting the next. Requiring another module from within Lua does basically the same thing. mw.loadData does all steps only once and relies on the read-only wrapping to prevent one invoke from affecting the next. Anomie 15:26, 26 February 2017 (UTC)
Sorry if I repeat myself: I'm asking if there is any way to declare a function that the parser can safetly cache its output jumping all these 4 steps. E.g. sqrt(5) is the same even if you call it 1000 times, no reasons to calculate it even in these last 2 steps. So, no way to instruct the parser about the existence of "functional" functions, which result that can be safetly cached when arguments are the same? --Valerio Bozzolan (talk) 23:39, 26 February 2017 (UTC)
No, there is no way to do that. Anomie 01:12, 27 February 2017 (UTC)
@Johnuniq @Anomie Thanks for the detailed answers! --Rotpunkt (talk) 08:47, 27 February 2017 (UTC)

Smart formatnum?[edit]

It was pointed out at Template talk:when#Breaks inside Infobox settlement that if you try to pass various inline cleanup templates through infoboxes which apply {{formatnum: }} that the year in the tracking category is mangled (comma inserted). would it be a good idea to create a smart formatnum which excludes the categories, and say references, from the formatnum transformation? or, does this already exist? thank you. Frietjes (talk) 22:14, 27 February 2017 (UTC)

maindate2[edit]

A trivial change (I suspect) is needed to a Lua module; please see Template talk:Article history#maindate2. Any takers? - Dank (push to talk) 03:14, 28 February 2017 (UTC)

Calling Mr. Stradivarius. The module is very sophisticated and mucking about with it could introduce a bunch of bad side effects. Johnuniq (talk) 04:19, 28 February 2017 (UTC)
Thanks John. - Dank (push to talk) 04:20, 28 February 2017 (UTC)

Wikidata: Extract a property from an item's property item[edit]

Hi,

I'm not sure if it's the right place to ask about this: is there any way to extract say the country property (P17) from the item linked to the headquarters location property (P159) of an item? For example, the headquarters location property of Nordea is Stockholm ; if we then look for the country property of Stockholm, we'll get Sweden. So if could get the country that way, we wouldn't need to set a country qualifier for the headquarters location property of Nordea, is there any way to do that? The RedBurn (ϕ) 21:40, 1 March 2017 (UTC)

@RexxS: Any thoughts? Johnuniq (talk) 00:34, 2 March 2017 (UTC)
Sure, John, I made a call in my sandbox module, Module:RexxS called getValueIndirect, that takes two property IDs as the first and second unnamed parameters, and returns the value of the second property of the value of the first property for the current article. So previewing a call for the country (P17) of the value of headquarters location (P159) in Nordea will give you:
  • {{#invoke:RexxS|getValueIndirect|P159|P17}} → Sweden
(you can add a |qid= for testing the call outside of the current article). The value of headquarters location (P159) in Nordea (Q1123823) is Stockholm (Q1754); and the value of country (P17) for Stockholm (Q1754) is Sweden (Q34). I'm just taking the first value of each property, assuming they are single-valued. You'd have to specify how you'd want to handle the situation if either were multi-valued.
The call is intrinsically expensive because it has to call another entity not the one connected to the current article. Note that the property headquarters location (P159) in Nordea (Q1123823) already has a qualifier, country (P17), set to Sweden (Q34) and it is clearly preferable in Lua to fetch that qualifier, when present. In this particular case, Nordea (Q1123823) also already has the property country (P17), set to Sweden (Q34), which is even simpler to extract. I suppose you could check if the article's Wikidata entry has the country set; if not, check if it has the country qualifier of the headquarters location set; if not, then make this indirect call. I think I'd want to know what was trying to be achieved before I went to that much effort. --RexxS (talk) 02:02, 2 March 2017 (UTC)
Thanks for all that trouble. Johnuniq (talk) 02:26, 2 March 2017 (UTC)
No trouble. It saves my old brain from going rusty. --RexxS (talk) 02:36, 2 March 2017 (UTC)
Awesome, thanks! About directly fetching the property country (P17) of an item, it's no always a good idea, for instance with d:Q67#P159 which is in France, but the main P17 value is multiple countries. It has been suggested to split that property into city, etc. but some users think the headquarters value should be as specific as possible (e.g. building for instance) - which actually makes it more difficult to use since we have to check what it represents - and that we should do a lot of expensive getValueIndirect calls to get the city, (state or other), and country. I thought about asking to auto set the country for P159, but if it's a building (or even a room in a floor of a building) instead of a city, it's not that easy. The RedBurn (ϕ) 13:02, 2 March 2017 (UTC)

Leakage[edit]

I am working on a location map wrapper in Module:Australian place map for use in Template:Infobox Australian place. I have implemented the module in the sandbox, and now in Template:Infobox Australian place/testcases I am seeing something strange. in particular, in the "Nyabing" I am currently seeing two pin markers, and in one of the "Woy Woy" examples, I am seeing zero pin markers. basically, it looks like the pin from the first "Woy Woy" has migrated up the page to the "Nyabing". my guess is that this is some quirk with using the {{Testcase table}} template and/or something odd going on in Module:Location map? on a related note, I imagine it would probably be better if I could call the main function in Module:Location map directly instead of going through expandTemplate? I am hoping Jackmcbarn or one of the other LUA experts can help. thank you. Frietjes (talk) 16:41, 4 March 2017 (UTC)

@Frietjes: It looks as if it is a simple mistake in Template:Infobox Australian place/testcases which has two Woy Woy tables, one with latd = -33.49 and that puts the pin a long way off the map. Johnuniq (talk) 00:56, 5 March 2017 (UTC)
Much later, something inside me muttered "oops, latitude is negative in Australia". Then I did a test and saw that {{Infobox Australian place}} gives identical results regardless of whether latd is positive or negative, so I looked at the template and see it is using #expr:abs to ignore the sign of latd. However, Module:Australian place map applies abs to the longitude rather than the latitude. Some mucking around makes me think you probably want abs(longitude) to avoid an ugly error message if a negative longitude is entered. However, the module needs the same for latitude, and that is why the pin is in the wrong place with the negative latitude. Johnuniq (talk) 09:38, 5 March 2017 (UTC)
Johnuniq, yes, that was dumb on my part. I can't believe I didn't see the fact that I had applied the abs to the long instead of the lat. thank you. Frietjes (talk) 13:57, 5 March 2017 (UTC)

Finding text using string.match on the currently edited page[edit]

I'm reuploading a lot of images using Commonist, which unfortunately overwrites file description pages. Is there a way to find text currently in the page (for example, the original uploader's username in the file information template) by transcluding the page, or does that not work because of Lua being parsed at the wrong time? Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
10:34, 5 March 2017 (UTC)

@Jc86035: You can get the wikitext of the current page with mw.title.getCurrentTitle():getContent(). You can also expand any templates etc. in that wikitext by using frame:preprocess. Whether you can manage to get useful information from either or both of those steps is another matter, however. — Mr. Stradivarius ♪ talk ♪ 23:37, 5 March 2017 (UTC)
I have often used 'getCurrentTitle' and 'getContent' (rarely 'frame.preprocess!) in order to do some minimal analysis of pages in WikiVoyage (get TOCs from another page, word analysis, search for a word or phrase, create a gallery of images found on a page in order to see if those images are in 'Commons' etc.) The main issue you will find is that there can be a lot of work actually parsing the page text (text processing) with Lua in order to find and identify what you are looking for. Also be aware of multiple variations and exceptions that you may have to code for. I agree with the above as to whether of not you will be able to obtain any useful information is in question. (note: besides 'string.match', you will also be using a lot of 'string.gsub', 'string.find' commands as well. - Best wishes and Good luck! -- Matroc (talk) 04:56, 7 March 2017 (UTC)

Another Lua request[edit]

Hey
I need help creating a module that will order 2 words alphabeticaly.
I did it in wiki code so I will explain how I did it, if you have better sugestions please offer:

  1. First, I created a template called he:תבנית:גימטריה - מאות למספר It basically takes a letter and gives it's number in Gimatria
  2. Then I took the first 2 letters of each word, if the first letter of X > Y then it will produce the text Y-X
  3. If the first letter of X < Y ==> X-Y
  4. If X=Y, it will do the same for the second letter, then for the third and that's it.
    • Note: before comparing you need to remove the geresh - ', I did it using {{replace}}.

Tagging User:Mr. Stradivarius who has helped me here before--Mikey641 (talk) 21:47, 7 March 2017 (UTC)

@Mikey641: Usually ordering words like this is done with the unicode collation algorithm, but there doesn't seem to be an implementation of it available in Scribunto. If you want to use Gimatria for only sorting Hebrew words, though, then that's certainly possible. You might try something like the following procedure (should work for any number of words, not just two):
  • Define a function that converts a hebrew character into its Gimatria number.
  • Remove the geresh from the words with string.gsub.
  • Convert the words into one of the unicode normalization forms, using e.g. mw.ustring.toNFD, in case strings which should be identical have different combining characters. (This would mean that they would have different unicode codepoints, which would affect comparisons.)
  • Put the words into a sequence (a Lua table with keys 1, 2, 3, etc.).
  • Sort the sequence using table.sort, specifying a custom sorting function. Your function should:
    • Accept two words.
    • Iterate over the codepoints in each of the words using a while loop and an index i starting at i = 1.
    • Find the i'th character in each of the strings using mw.ustring.codepoint and mw.ustring.char (mw.ustring.char(mw.ustring.codepoint(s, i, i))).
    • Find the Gimatria number for each of those characters, return true if the number for the character from the first string should sort before the one for the second string, and return false if it should sort after. If the Gimatria numbers are equal, keep iterating.
    • If all the Gimatria numbers are the same, the strings are (in effect) equal, so return either true or false. It doesn't matter which, unless you want to order Gimatria-identical strings in some other way as well.
  • When you have sorted your table, you can output it however you want. For example, you could join all the strings together into one big string (with a separator) using table.concat.
Unicode can be a bit tricky so I might have got some of this wrong, but this is the basic idea of what you will need to do. Let me know if you need any more help. Best — Mr. Stradivarius ♪ talk ♪ 02:38, 9 March 2017 (UTC)
  • Interesting discussion. As an aside, I am wondering if besides 'garesh' would you want to replace 'gershayim'. Also, would one have to be concerned that an 'apostrophe 0027' might have been used for the 'garesh' character and 'quotation mark 0022' for the 'gershayim' character. -- Cheers! Matroc (talk) 05:25, 9 March 2017 (UTC)

Gating lua functions[edit]

So, we are using a system in hewiki to "verify" template parameters. i will be happy to explain about the system, but my question here is a bot different:

it turns out that this system adds significant load to some template parsing, and this cases a small number of pages to violate some limits of the parser, and these pages then are not parsed correctly.

the only remedy we found so far is to completely (i.e., globally) disable this system - if we do that, the pages are parsed ok.

what we are looking for, is a way to gate specific lua functions, based on the some attribute of the page, something similar to {{Nobots}}, for lua modules.

it is perfectly kosher to use something like categories (naturally, it will be a hidden one), i.e., i will be happy to define a new hidden category, say "No template parameters validation", and add those pages to the category. however, i could not find a way to ask in lua "does this page belong to category X", or "give me the list of categories this page belongs to". i cannot think of something other than category that will do the job, but i am willing to learn any new tricks.

note that the #invoke call is not in the page itself, but rather pretty deep in some templates (many may not even be transcluded directly, but through other templates, going 2, 3 and even 4 levels deep).

any help and advice will be appreciated. peace - קיפודנחש (aka kipod) (talk) 16:04, 12 March 2017 (UTC)

@קיפודנחש: While there's no way to find the categories of a page in Scribunto as far as I'm aware, there are two ways of doing this that I can think of. The first is to have a flag in the page content and parse it using something like mw.title.getCurrentTitle():getContent():find('__NOPARAMETERVALIDATION__'). The second is to have a blacklist module with e.g. return {['Page name 1'] = true, ['Page name 2'] = true} which you check before doing the validation. I'd be quite interested in hearing about the system you are using, though - what kind of parameter verification are you doing that's creating so much load? — Mr. Stradivarius ♪ talk ♪ 23:39, 12 March 2017 (UTC)
thanks. your second suggestion is what we actually already do, i.e., keeping a "blacklist" (except we call it "verboten"), and is what i wanted to avoid - i think it would be nicer and better to let pages self-blacklist, and it would require less maintenance. as to your first suggestion, well, it would work, but it would completely miss the point - the whole point of the exercise is to avoid calling getContent() (albeit for the template rather than for the page, but TBH, in most cases, in in all actual cases where we want to blacklist, doing it for the template is actually cheaper....). bottom line: thanks for your suggestions, and i appreciate the thought, but unfortunately, the first one is what we try to avoid, and the second won't work for us....
just to complete the picture, what we do is something like:
local verbotten = {
    ['page name 1'] = '',
    ['page name 2' = '',
-- ..... etc. etc. etc.
}

function envelope( frame )
    local pageName = mw.title.getCurrentTitle().text

-- exploiting the fact that unline JS, in lua '' is actually true
    return verbotten[pageName] or require( 'actualModule' ).actualFunction( frame ) 
end
as to your question: i am not sure 100% about the load, but i suspect it's not from the verification itself, but rather from the fact that mediawiki neglected to create the mw.templateData.getTemplateData( templatename ), which is open for ~ 2 years now. "they" actually put "priorily:lowest" on it (see phab:T107119, so we call getContent() on the template page,, distill the stuff enclosed inside the "templatedata" tag, and call "jsonDecode()" on it. after that, the rest is trivial. you may want to look in he:Module:ParamValidator - i tried to document it as much as possible. the system is working, and exposed thousands (literally) of errors in templates.
peace - קיפודנחש (aka kipod) (talk) 04:30, 13 March 2017 (UTC)
That kind of work should be done by a bot rather than a module that is implementing a template. Johnuniq (talk) 04:44, 13 March 2017 (UTC)
@Johnuniq: - no argument here (except to advocate that this shouldn't even be done by a bot - it's a natural thing for mw:Extension:TemplateData to implement as part of the extension: the whole idea of defining parametr as "required", is to add the page to tracking category when it's missing, same for "type" as number and "obsolete" parameter). unfortunately, the templatedata development team did not do it, and i am not aware of a bot that does it. do you happen to have such a bot? until "someone" implement it in the extension, or "someone" writes a bot, we are sticking with the lua implementation. peace - קיפודנחש (aka kipod) (talk) 04:55, 13 March 2017 (UTC)

Location map / infobox map[edit]

There was some discussion at TfD about Template:Infobox map. basically, all that Template:Infobox map does right now is (1) check to see if the map exists, and then (2) call either Template:Location map or Module:InfoboxImage. this is somewhat inefficient since there is already an ifexists check in the getMapParams function in Module:Location map. so, my thought is that we could change the code of {{infobox map}} to something like

{{location map|{{{map}}}
  | relief = {{{relief|}}}
  | overlay_image = {{{overlay|}}}
[...]
  | nomap_message = {{#invoke:InfoboxImage | InfoboxImage | image={{{map}}} | size={{{map_width|}}} | maxsize={{{max_width|}}} | sizedefault={{if empty|{{{default_width|}}}|220px}} | alt={{{map_alt|}}} | title={{{map_caption|}}} }}{{#if:{{{map_caption|}}}|<div>{{{map_caption|}}}</div>}}
}}

so, that instead of returning the error message on line 50 of Module:Location map it would return the value of |nomap_message= if |nomap_message= is not nil. does this seem like a good idea? if so, it would be helpful if someone could implement this |nomap_message= in Module:Location map/sandbox for testing. I would do it, but I am not sure the best way to pass this through to the getMapParams function and the best way to catch it when it comes out of the getMapParams function. probably need a second return flag with 0 for no error, and 1 for error or something like that? thank you. Frietjes (talk) 16:35, 16 March 2017 (UTC)

Module:Navbox with nowrap lists[edit]

Information.svg

An editor has asked for a discussion regarding Module:Navbox with nowrap lists. Input from those familiar with modules is welcome at Wikipedia:Miscellany for deletion/Module:Navbox with nowrap lists. Thanks, — Godsy (TALKCONT) 09:11, 20 December 2016 (UTC)

Not Wikipedia:Miscellany for deletion/Module:Navbox with nowrap lists? – Uanfala (talk) 21:21, 21 March 2017 (UTC)
@Uanfala: Corrected, thanks. I borrowed from my format of Wikipedia talk:Lua/Archive 5#Module:PropertyLink MfD above and overlooked that part. — Godsy (TALKCONT) 03:34, 22 March 2017 (UTC)

Replacing HTML character entities with normal characters[edit]

How can I modify Module:Tone superscript so that it only adds superscript tags to numbers not part of HTML entities (or filenames/links/anything which breaks when <sup> tags are added)? The module was originally written by someone else but I'm trying to repurpose it so it works in {{Infobox Chinese}}. Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
09:15, 24 March 2017 (UTC)

I looked very quickly. This does not address your question but wouldn't you want the following (note the +):
x = arg:gsub("(%d+)", "<sup>%1</sup>")
I do not understand the scenario. Where would the code be used? That is, would it change some of the parameters to the infobox, or change some of the output? I can't think of a reason why digits should be automatically superscripted.
The heading of this section suggests that code to change an entity to a character is wanted? Is that right? Johnuniq (talk) 09:42, 24 March 2017 (UTC)
@Johnuniq: In the Wade–Giles romanization of Mandarin, tone numbers are superscript, but the tone numbers might not be superscripted by users. The output of {{Infobox Chinese/Chinese}} would be changed. The original author didn't bother with the +, which isn't really a problem since there are fewer than 10 tones in most tonal languages. The module could have the entities changed to characters to avoid inserting <sup> tags in them, although there could be a better solution. Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
12:37, 24 March 2017 (UTC)
If I understand this correctly, you want to be able to parse arbitrary wikitext input, discard the parts that have a special meaning in wikitext, and alter the other parts? Unfortunately, in the general case at least, this requires a wikitext parser, and no-one has written a wikitext parser in Lua yet, as far as I know. In some cases you may be able to muddle through, but to do it accurately, you need a parser. If I were writing a module like this, then rather than trying to parse everything, I would be inclined to be strict about what input the module accepts, and then raise an error if the module detects invalid input. You can make this error a silent one at first (just adding a tracking category) to avoid generating too many pages with big red error notices. — Mr. Stradivarius ♪ talk ♪ 15:28, 24 March 2017 (UTC)
An infobox at Jackie Chan includes the wikitext:
| j3 = {{Jpingauto|Can4 Gong2 Sang1}}
Template:Jpingauto is a redirect to {{Tone superscript}}, and the above example outputs Can4 Gong2 Sang1.
Is the proposal that the template would be retained but would be modified to avoid damaging certain parameters?
Or, is the proposal that the code from the module would be integrated into the infobox so that the template is not needed?
Or, something else?
Assuming the template would be retained, as Mr. Stradivarius says, a general solution would be too complex. However, if the template only has to handle an input that might have entities like &#8211; or &#x2013;, and might have a link which should not be damaged, I could fix the module. Johnuniq (talk) 06:25, 25 March 2017 (UTC)
@Johnuniq and Mr. Stradivarius: The easiest solution without messing with parsing pages in the module would probably be to add a tracking category in Infobox Chinese/Chinese for templates containing unexpected characters, run over all the pages using template with Joe's Null Bot, and replace all the XML entities before re-adding {{Tone superscript}}. It could potentially still be problematic if there are things like pronunciation templates though. Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
06:43, 25 March 2017 (UTC)
Wouldn't it be easier to make the module apply <sup>...</sup> to a digit only if it's preceded by letters? – Uanfala (talk) 08:40, 25 March 2017 (UTC)
@Uanfala: The problem is that character entities in hexadecimal can contain letters a–f and x, which prevents that from working. Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
09:53, 25 March 2017 (UTC)
I see. Maybe it can exclude strings starting with & and ending with ;, just as it will exclude ones enclosed in double square brackets? An alternative would be to use mw.text.decode to convert the html entities to the unescaped characters, but it will need checking whether any of them wouldn't disrupt the template that calls the module. – Uanfala (talk) 09:59, 25 March 2017 (UTC)
@Uanfala: I didn't realize that function existed. I don't think the template would be disrupted, since there shouldn't be a wide variety of characters in the input anyway, and vertical bars and such output by Scribunto can't be used to construct templates. Jc86035 (talk) Use {{re|Jc86035}}
to reply to me
10:31, 25 March 2017 (UTC)