- このヘルプには更新、または翻訳されていないコンテンツがあります。どなたでも翻訳にご協力いただくことができます。
- 原文 : w:c:dev:Lua templating/Converting Wikitext templates。
ウィキテキストテンプレートを、Luaテンプレートに書き換える方法を紹介します。
Switch 命令文[]
読み込みに時間がかかるテンプレートで一番よくあるのは、情報量の多い{{#switch:}}
命令文を使ったものです。これらは、大抵の場合、同じページで何度も呼び出されています。mw.loadData
と、簡単なデータ表を使うことで、そのようなテンプレートの読み込みをだいぶ速くすることができます。簡単なLuaデータ表を使ったLuaテンプレートでは、おおよそ定数時間O(1)でハッシュテーブルのデータを探索します。また、mw.loadData()
を使用すると、Module:FooBar の使用回数にかかわらず、そのページ内で読み込まれるのは一度だけです。150項目のSwitch命令文があるテンプレートで比較すると、以上のようなLuaテンプレートに置き換えることで、構文解析の時間をおよそ50%短縮することができます。
例として、以下のようなSwitch命令文を使ったテンプレートを書き換えてみましょう。
{{#switch:{{{1|}}} | case 1 = Foo | case 2 = Bar | case 3 | case 4 = FooBar | #default: {{{1|}}} }}
このテンプレートをLuaテンプレートに書き換えるために、2つのモジュールページを作成します。
Module:FooBar:
local p = {}
local fooBarData = mw.loadData( 'Module:FooBar/data' )
function p.fooBar( frame )
local fooBarText = frame.args[1]
return fooBarData[fooBarText] or fooBarText or ""
end
return p
Module:FooBar/data:
return {
["case 1"] = "Foo",
["case 2"] = "Bar",
["case 3"] = "FooBar",
["case 4"] = "FooBar",
--["default"] = ""
}
使用方法
{{#invoke:fooBar|fooBar|case 1}}
出力:
Foo
※mw.loadDataで使う配列は関数を入れる事ができません。
Conditional statements (#if)[]
Many templates make use of "#if" parser functions resulting in a lot of nested functions, which may make the code very complex and hard to understand. This can be converted and made more efficient using Lua. See live demo.
For example, to create template that checks if a template argument contains "text", one would write something like:
{{#if:{{{1|}}}|You entered text|No text}}
This can be converted to: Module:if :
local p = {}
function p.main( frame )
local tArgs = frame:getParent()
if not(tArgs.args[1]) then
tArgs = frame
end
local sText = tArgs.args[1]
local sTrueAction = tArgs.args[2] or tArgs.args["true"]
local sFalseAction = tArgs.args[3] or tArgs.args["false"]
if sText == nil or sText == "" then
sText = mw.getCurrentFrame():preprocess(sFalseAction)
else
sText = mw.getCurrentFrame():preprocess(sTrueAction)
end
return sText
end
return p
This can be applied to complex "#if" based parser functions, and would be much easier to understand.
Check if article exists (#ifexists)[]
Create Module:ifexists :
local p = {}
function p.exists( frame )
local tArgs = frame:getParent()
if not(tArgs.args[1]) then
tArgs = frame
end
local sText = tArgs.args[1]
local sTrueAction = tArgs.args[2] or tArgs.args["true"]
local sFalseAction = tArgs.args[3] or tArgs.args["false"]
if sText and sText ~= "" then
if mw.title.new( sText ).exists then
return sTrueAction
else
return sFalseAction
end
end
end
return p
Then simply use {{#invoke:existpage|exists|pagename|yep|nop}} .
Note: This sadly still remains an expensive function.
One can remove the "expensive" nature of the above function by using the hack below. However, this hack can actually be worse because it transcludes a whole page.
local p = {}
function p.exists(frame)
local sPage = frame.args[1]
if sPage then
local num = frame:preprocess('{{:'..sPage..'}}')
if string.sub(num,1,3) ~="[[:" then
return frame.args[2] or frame.args["true"]
end
end
return frame.args[3] or frame.args["false"]
end
return p
This method is not recommended.
However, yet another approach can be used to inexpensively check if a module exists:
local p = {}
function p.exists(frame)
local sPage = frame.args[1]
if sPage then
local _, val = pcall(package.loaders[2], sPage)
if type(val) == "function" or type(val) == "string" then
return frame.args[2] or frame.args["true"]
end
end
return frame.args[3] or frame.args["false"]
end
return p
Loop Statements (#for)[]
One way to reduce the template size, and to make it load faster and more efficiently is to reduce repeated text. This can typically be achieved by using loops or using Lua.
A template that repeats some text can be created using the loops extension by using:
Template:foo {{ #for: {{{n}}} | {{{list$n$}}} ♣ }}
Template use:
{{ foo: |n=4 | list1=a | list2=b | list3=c | list4=d }}
Output:
a♣b♣c♣d♣
This can be converted to Module:loop:
local p = {}
function p.appendloop( frame )
local tArgs = frame:getParent()
if not(tArgs.args[1]) then
tArgs = frame
end
local sOutputText = ""
for iKey,sValue in pairs(tArgs.args) do
sOutputText = sOutputText .. sValue .. "♣"
end
return sOutputText
end
return p
Template:foo :
{{#invoke:loop|appendloop}}
Calling template foo with these arguments:
{{foo|a|b|c|d}}
Results in :
a♣b♣c♣d♣
Time function (#time)[]
Time functions can be converted with the following module:time :
local p = {}
function p.getdate( frame )
local sText = frame.args[1]
local sTimestamp = frame.args[2]
local sLangCode = frame.args[3]
local lang = mw.language.new(sLangCode or "en")
if sText then
return lang:formatDate(sText, sTimestamp)
end
end
return p
This can then be called using : {{#invoke:time|getdate|Y-m-d|2013-10-04|fr}}
This shows the date, e.g. 2013-10-04. The special characters used to get this date can be found in mediawiki.
Text manipulation functions[]
The table below lists some common text manipulation functions (StringFunctions) commonly used in wikis. Some of these are available in the Global Lua Modules/String.
Length (#len)[]
{{#len:Icecream}}
local text = "Icecream"
local results = string.len(text)
print(results)
Output: 8
Position (#pos)[]
{{#pos:Žmržlina|lina}}
local text = "Žmržlina"
local results, e = string.find(text, "lina")
print(#text + 1 - results)
Output: 4
Substring (#sub)[]
{{#sub:Icecream|0|3}}
local text = "Icecream"
local results = string.sub(text, 1, 3)
print(results)
Output: Ice
Repeat (#pad)[]
{{#pad:Ice|5|x|left}}
local text = "Ice"
local results = string.rep("x", 5 - #text) .. text
print(results)
Output: xxIce
Replace (#replace)[]
{{#replace:Žmržlina|ž|z}}
local text = "Žmržlina"
local results = string.gsub(text ,"ž","z")
print(results)
Output: Žmrzlina
Explode (#explode)[]
The "Explode" function can divide a piece of text and show the part needed. This is a parser function that was a subject of much argument and debate over close to a decade or more and one of the reasons for existence of scribunto[1]. This was primarily due to its useful ability to extract sections or parts of a text.
Its syntax is be something like:
{{#explode:And if you tolerate this| |2}} -> you
Scribunto is hundreds of times more efficient[2], and can be written as:
local text = "And if you tolerate this"
local tab = mw.text.split( text, " ")
print(tab[3])
Output: you
Extracting text[]
One can even do more complex things such as extracting arbitrary text using lua patterns :
local text = "Jameson, J. (2013). E-Leadership in higher education"
local surname,initials, year = string.match( text, "(%a*)%s*,%s*(%S*)%s*(%b())")
print( year, initials, surname)
(2013) J. Jameson
Urlencode #urlencode[]
Output: x%3Ay%2Fz+%C3%A1+%C3%A9
Urldecode #urldecode[]
{{urldecode:x%3Ay%2Fz+%C3%A1+%C3%A9}}
local results = mw.uri.decode("x%3Ay%2Fz+%C3%A1+%C3%A9","QUERY")
print(results)
Output: x:y/z á é
Number formatting[]
There are a number of parser functions (see this) to format numbers such as Extension:Formatnum and Extension:Parser functions. Despite having the exact same name, they have different syntax and are largely incompatible.
Formatnum[]
{{formatnum:1231231}}
local number = 1231231
local noCommas = false
local lang = mw.language.new("en")
local result = lang:formatNum(number, {noCommafy=noCommas})
mw.log(result)
Output : 1,231,231
関連情報[]
- Developers Wiki - Converting Wikitext templates … このページの元になった記事
注釈[]
その他のヘルプとフィードバック[]
- ヘルプ:コンテンツでは、他のヘルプページを閲覧、検索することができます。
- 最新の情報やヘルプについては、コミュニティセントラルをご覧ください。
- この記事で不明確な点や、曖昧な点がございましたら、Fandomとの連絡方法をご確認ください。
- このヘルプはコミュニティセントラル内にて管理されています。