# 扩展:Scribunto/Lua参考手册

This page is a translated version of the page Extension:Scribunto/Lua reference manual and the translation is 75% complete.
Other languages:
Bahasa Indonesia • ‎Deutsch • ‎English • ‎Esperanto • ‎Tiếng Việt • ‎Türkçe • ‎asturianu • ‎català • ‎español • ‎français • ‎italiano • ‎magyar • ‎polski • ‎português do Brasil • ‎русский • ‎українська • ‎עברית • ‎ဖၠုံလိက် • ‎မြန်မာဘာသာ • ‎中文 • ‎日本語 • ‎한국어

Lua manual
LUAREF

## 介绍

### 入门

local p = {} --p代表一个包（package）

function p.hello( frame )
return "Hello, world!"
end

return p


{{#invoke:Bananas|hello}}


### 从维基文本关联参数

{{#invoke:}}调用函数时，会将框架项目（frame object）作为调用函数时的参数（参数只有一个）。要关联被{{#invoke:}}通过的函数，代码通常会使用框架项目的args。也可以关联被包含{{#invoke:}}的模板参数，方法是使用frame:getParent() 然后关联到框架的args

### 模块文档

Scruibunto允许模块可以被自动关联的模块维基文本页面关联文档；默认情况下，模块的“/doc”子页面是用来作为文档，并且会在模块页面的代码顶部显示其内容。例如，“模块:Bananas”的文档页面就是“模块:Bananas/doc”。

• scribunto-doc-page-name（文档页面名称）：设置用来作文档页面的名称。模块（除了模块:prefix）的名称会通过$1。如果在模块命名空间，这里的页面通常会视为维基文本而不是Lua代码，也不会被{{#invoke:}}使用。模块的页面通常是“Module:$1/doc”这样的模块/doc子页面。注意解析器函数等其他可扩展代码在这个消息中不被使用。
• scribunto-doc-page-does-not-exist（文档页面不存在）：消息会在文档页面不存在时显示。页面名称通常会通过$1。默认是空的。 • scribunto-doc-page-show（文档页面显示）：当文档页面存在时，消息就会显示。页面的名称通常会通过$1。默认是引用文档页面。

#### string.gmatch

string.gmatch( s, pattern )

#### string.gsub

string.gsub( s, pattern, repl, n )

#### string.len

string.len( s )

#### string.lower

string.lower( s )

#### string.match

string.match( s, pattern, init )

#### string.rep

string.rep( s, n )

#### string.reverse

string.reverse( s )

#### string.sub

string.sub( s, i, j )

#### string.upper

string.upper( s )

• 样式匹配本身不认识像'\"ddd"'这样的转义。然而，由于样式匹配是字符串，这一类转义或许可以用于在创建样式匹配字符串的文字。

#### mw.isSubsting

mw.isSubsting()

mw.loadData( module )

mw.loadData类似于require()，但是有以下区别：

• 加载的模块每页只会解析一次，而不是每次调用{{#invoke:}}就解析一次。
• 加载的模块不会记录在package.loaded中。

• 返回的表（以及其所有子表）智能包含布尔值、数字、字符串和其他表。其他的数据类型，比如函数，不允许。
• 返回的表（和所有子表）不能有metatable元表。
• 所有的表键必须是布尔值、数字、字符串。
• mw.loadData()返回的表提供元方法，可以提供只读获取由模块返回的表。因为不能直接包含数据，pairs()ipairs()会起作用，但是像#valuenext()这样的函数和表库的函数不会起作用。

#### mw.dumpObject

mw.dumpObject( object )

object序列化为人类可读的字符串并返回。

#### mw.log

mw.log( ... )

#### mw.logObject

mw.logObject( object )
mw.logObject( object, prefix )

### 框架对象（Frame object）

#### frame.args

{{#invoke:module|function|arg1|arg2|name=arg3}}


#### frame:callParserFunction

frame:callParserFunction( name, args )
frame:callParserFunction( name, ... )
frame:callParserFunction{ name = string, args = table }

-- {{ns:0}}
frame:callParserFunction{ name = 'ns', args = 0 }

-- {{#tag:nowiki|some text}}
frame:callParserFunction{ name = '#tag', args = { 'nowiki', 'some text' } }
frame:callParserFunction( '#tag', { 'nowiki', 'some text' } )
frame:callParserFunction( '#tag', 'nowiki', 'some text' )
frame:callParserFunction( '#tag:nowiki', 'some text' )

-- {{#tag:ref|some text|name=foo|group=bar}}
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', name = 'foo', group = 'bar'
} }


#### frame:expandTemplate

frame:expandTemplate{ title = title, args = table }

frame:expandTemplate{ title = 'template', args = { 'arg1', 'arg2', name = 'arg3' } }


-- 这与维基文本{{template|{{!}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '|' } }

-- 这与维基文本{{template|{{((}}!{{))}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '{{!}}' } }


#### frame:extensionTag

frame:extensionTag( name, content, args )
frame:extensionTag{ name = string, content = string, args = table_or_string }

-- 这些都相同
frame:extensionTag{ name = 'ref', content = 'some text', args = { name = 'foo', group = 'bar' } }
frame:extensionTag( 'ref', 'some text', { name = 'foo', group = 'bar' } )

frame:callParserFunction{ name = '#tag:ref', args = {
'some text', name = 'foo', group = 'bar'
} }

-- 这些都相同
frame:extensionTag{ name = 'ref', content = 'some text', args = 'some other text' }
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', 'some other text'
} }


#### frame:getParent

frame:getParent()

#### frame:getTitle

frame:getTitle()

#### frame:newChild

frame:newChild{ title = title, args = table }

#### frame:preprocess

frame:preprocess( string )
frame:preprocess{ text = string }

#### frame:getArgument

frame:getArgument( arg )
frame:getArgument{ name = arg }

#### frame:newParserValue

frame:newParserValue( text )
frame:newParserValue{ text = text }

#### frame:newTemplateParserValue

frame:newTemplateParserValue{ title = title, args = table }

#### frame:argumentPairs

frame:argumentPairs()

### 哈希库

#### mw.hash.hashValue

mw.hash.hashValue( algo, value )

#### mw.hash.listAlgorithms

mw.hash.listAlgorithms()

### HTML库

mw.html是用于在Lua中构建复杂HTML树的友好接口。使用mw.html.create方法来创建mw.html对象。

local div = mw.html.create( 'div' )
div
:attr( 'id', 'testdiv' )
:css( 'width', '100%' )
:wikitext( 'Some text' )
:tag( 'hr' )
-- Output: <div id="testdiv" style="width:100%;">Some text<hr /></div>


#### mw.html.create

mw.html.create( tagName, args )

args可以是有以下键的表：

• args.selfClosing：强制当前标签自我闭合，即使mw.html不认可其自我闭合
• args.parent：当前mw.html实例的上级对象（用于内部使用）

#### mw.html:node

html:node( builder )

#### mw.html:wikitext

html:wikitext( ... )

#### mw.html:newline

html:newline()

#### mw.html:tag

html:tag( tagName, args )

#### mw.html:attr

html:attr( name, value )
html:attr( table )

#### mw.html:getAttr

html:getAttr( name )

html:addClass( class )

#### mw.html:css

html:css( name, value )
html:css( table )

#### mw.html:cssText

html:cssText( css )

#### mw.html:done

html:done()

#### mw.html:allDone

html:allDone()

### 语言库

#### mw.language.fetchLanguageName

mw.language.fetchLanguageName( code, inLanguage )

The full name of the language for the given language code: native name (language autonym) by default, name translated in target language if a value is given for inLanguage.

#### mw.language.fetchLanguageNames

mw.language.fetchLanguageNames()
mw.language.fetchLanguageNames( inLanguage )
mw.language.fetchLanguageNames( inLanguage, include )

Fetch the list of languages known to MediaWiki, returning a table mapping language code to language name.

By default the name returned is the language autonym; passing a language code for inLanguage returns all names in that language.

By default, only language names known to MediaWiki are returned; passing 'all' for include will return all available languages (e.g. from Extension:CLDR), while passing 'mwfile' will include only languages having customized messages included with MediaWiki core or enabled extensions. To explicitly select the default, 'mw' may be passed.

#### mw.language.getContentLanguage

mw.language.getContentLanguage()
mw.getContentLanguage()

Returns a new language object for the wiki's default content language.

#### mw.language.getFallbacksFor

Fallback chains

mw.language.getFallbacksFor( code )

Returns a list of MediaWiki's fallback language codes for the specified code.

#### mw.language.isKnownLanguageTag

mw.language.isKnownLanguageTag( code )

Returns true if a language code is known to MediaWiki.

A language code is "known" if it is a "valid built-in code" (i.e. it returns true for mw.language.isValidBuiltInCode) and returns a non-empty string for mw.language.fetchLanguageName.

#### mw.language.isSupportedLanguage

mw.language.isSupportedLanguage( code )

Checks whether any localisation is available for that language code in MediaWiki.

A language code is "supported" if it is a "valid" code (returns true for mw.language.isValidCode), contains no uppercase letters, and has a message file in the currently-running version of MediaWiki.

It is possible for a language code to be "supported" but not "known" (i.e. returning true for mw.language.isKnownLanguageTag). Also note that certain codes are "supported" despite mw.language.isValidBuiltInCode returning false.

#### mw.language.isValidBuiltInCode

mw.language.isValidBuiltInCode( code )

Returns true if a language code is of a valid form for the purposes of internal customisation of MediaWiki.

The code may not actually correspond to any known language.

A language code is a "valid built-in code" if it is a "valid" code (i.e. it returns true for mw.language.isValidCode); consists of only ASCII letters, numbers, and hyphens; and is at least two characters long.

Note that some codes are "supported" (i.e. returning true from mw.language.isSupportedLanguage) even though this function returns false.

#### mw.language.isValidCode

mw.language.isValidCode( code )

Returns true if a language code string is of a valid form, whether or not it exists. This includes codes which are used solely for customisation via the MediaWiki namespace.

The code may not actually correspond to any known language.

A language code is valid if it does not contain certain unsafe characters (colons, single- or double-quotes, slashs, backslashs, angle brackets, ampersands, or ASCII NULs) and is otherwise allowed in a page title.

#### mw.language.new

mw.language.new( code )
mw.getLanguage( code )

Creates a new language object. Language objects do not have any publicly accessible properties, but they do have several methods, which are documented below.

There is a limit on the number of distinct language codes that may be used on a page. Exceeding this limit will result in errors.

#### mw.language:getCode

lang:getCode()

Returns the language code for this language object.

#### mw.language:getFallbackLanguages

lang:getFallbackLanguages()

Returns a list of MediaWiki's fallback language codes for this language object. Equivalent to mw.language.getFallbacksFor( lang:getCode() ).

#### mw.language:isRTL

lang:isRTL()

Returns true if the language is written right-to-left, false if it is written left-to-right.

#### mw.language:lc

lang:lc( s )

Converts the string to lowercase, honoring any special rules for the given language.

When the Ustring library is loaded, the mw.ustring.lower() function is implemented as a call to mw.language.getContentLanguage():lc( s ).

#### mw.language:lcfirst

lang:lcfirst( s )

Converts the first character of the string to lowercase, as with lang:lc().

#### mw.language:uc

lang:uc( s )

Converts the string to uppercase, honoring any special rules for the given language.

When the Ustring library is loaded, the mw.ustring.upper() function is implemented as a call to mw.language.getContentLanguage():uc( s ).

#### mw.language:ucfirst

lang:ucfirst( s )

Converts the first character of the string to uppercase, as with lang:uc().

#### mw.language:caseFold

lang:caseFold( s )

Converts the string to a representation appropriate for case-insensitive comparison. Note that the result may not make any sense when displayed.

#### mw.language:formatNum

lang:formatNum( n )
lang:formatNum( n, options )

Formats a number with grouping and decimal separators appropriate for the given language. Given 123456.78, this may produce "123,456.78", "123.456,78", or even something like "١٢٣٬٤٥٦٫٧٨" depending on the language and wiki configuration.

The options is a table of options, which can be:

• noCommafy: Set true to omit grouping separators and use a dot (.) as the decimal separator. Digit transformation may still occur, which may include transforming the decimal separator.

#### mw.language:formatDate

lang:formatDate( format, timestamp, local )

Formats a date according to the given format string. If timestamp is omitted, the default is the current time. The value for local must be a boolean or nil; if true, the time is formatted in the wiki's local time rather than in UTC.

The format string and supported values for timestamp are identical to those for the #time parser function from 扩展:解析器函数. Note however that backslashes may need to be doubled in a Lua string literal, since Lua also uses backslash as an escape character while wikitext does not:

-- This string literal contains a newline, not the two characters "\n", so it is not equivalent to {{#time:\n}}.
lang:formatDate( '\n' )

-- This is equivalent to {{#time:\n}}, not {{#time:\\n}}.
lang:formatDate( '\\n' )

-- This is equivalent to {{#time:\\n}}, not {{#time:\\\\n}}.
lang:formatDate( '\\\\n' )


#### mw.language:formatDuration

lang:formatDuration( seconds )
lang:formatDuration( seconds, allowedIntervals )

Breaks a duration in seconds into more human-readable units, e.g. 12345 to 3 hours, 25 minutes and 45 seconds, returning the result as a string.

allowedIntervals, if given, is a table with values naming the interval units to use in the response. These include 'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', and 'seconds'.

#### mw.language:parseFormattedNumber

lang:parseFormattedNumber( s )

This takes a number as formatted by lang:formatNum() and returns the actual number. In other words, this is basically a language-aware version of tonumber().

#### mw.language:convertPlural

lang:convertPlural( n, ... )
lang:convertPlural( n, forms )
lang:plural( n, ... )
lang:plural( n, forms )

This chooses the appropriate grammatical form from forms (which must be a sequence table) or ... based on the number n. For example, in English you might use n .. ' ' .. lang:plural( n, 'sock', 'socks' ) or n .. ' ' .. lang:plural( n, { 'sock', 'socks' } ) to generate grammatically-correct text whether there is only 1 sock or 200 socks.

The necessary values for the sequence are language-dependent, see localization of magic words and translatewiki's FAQ on PLURAL for some details.

#### mw.language:convertGrammar

lang:convertGrammar( word, case )
lang:grammar( case, word )

Note the different parameter order between the two aliases. convertGrammar matches the order of the method of the same name on MediaWiki's Language object, while grammar matches the order of the parser function of the same name, documented at Special:MyLanguage/Help:Magic words#Localisation.

This chooses the appropriate inflected form of word for the given inflection code case.

The possible values for word and case are language-dependent, see Special:MyLanguage/Help:Magic words#Localisation and translatewiki:Grammar for some details.

#### mw.language:gender

lang:gender( what, masculine, feminine, neutral )
lang:gender( what, { masculine, feminine, neutral } )

Chooses the string corresponding to the gender of what, which may be "male", "female", or a registered user name.

#### mw.language:getArrow

lang:getArrow( direction )

Returns a Unicode arrow character corresponding to direction:

• forwards: Either "→" or "←" depending on the directionality of the language.
• backwards: Either "←" or "→" depending on the directionality of the language.
• left: "←"
• right: "→"
• up: "↑"
• down: "↓"

#### mw.language:getDir

lang:getDir()

#### mw.language:getDirMark

lang:getDirMark( opposite )

Returns a string containing either U+200E (the left-to-right mark) or U+200F (the right-to-left mark), depending on the directionality of the language and whether opposite is a true or false value.

#### mw.language:getDirMarkEntity

lang:getDirMarkEntity( opposite )

Returns "&lrm;" or "&rlm;", depending on the directionality of the language and whether opposite is a true or false value.

#### mw.language:getDurationIntervals

lang:getDurationIntervals( seconds )
lang:getDurationIntervals( seconds, allowedIntervals )

Breaks a duration in seconds into more human-readable units, e.g. 12345 to 3 hours, 25 minutes and 45 seconds, returning the result as a table mapping unit names to numbers.

For example, { ['hours'] = 3, ['minutes'] = 25, ['seconds'] = 45 }

allowedIntervals, if given, is a table with values naming the interval units to use in the response. These include 'millennia', 'centuries', 'decades', 'years', 'days', 'hours', 'minutes', and 'seconds'.

The unit names in allowedIntervals may be specified in any order (currently in English only, indendantly of the language object used, and with their plural unabbreviated form only like in the returned table, where unit names are symbolic but still not translated and not grammatically changed according to their assigned value). If the input table contains only unsupported unit names, the returned table will be empty. If the input table is not specified, is nil, or is empty, a static table for any supported units (including 'seconds' for the shortest unit) will be used by default.

The specified duration in seconds is first rounded down to an integer number of the shortest desired unit. The number of members in the returned array is variable, and only unit names mapped to a non-zero value are kept in the returned table if the rounded number of seconds is strictly positive. Otherwise only the member for the shortest desired unit name ('seconds' by default) will be set to the rounded down duration.

### 系统消息库

#### mw.message.new

mw.message.new( key, ... )

#### mw.message.newFallbackSequence

mw.message.newFallbackSequence( ... )

#### mw.message.newRawMessage

mw.message.newRawMessage( msg, ... )

#### mw.message.rawParam

mw.message.rawParam( value )

#### mw.message.numParam

mw.message.numParam( value )

#### mw.message.getDefaultLanguage

mw.message.getDefaultLanguage()

#### mw.message:params

msg:params( ... )
msg:params( params )

#### mw.message:rawParams

msg:rawParams( ... )
msg:rawParams( params )

:params()，但是会先通过mw.message.rawParam()传递所有的参数。

#### mw.message:numParams

msg:numParams( ... )
msg:numParams( params )

:params()，但是会先通过mw.message.numParam()传递所有的参数。

#### mw.message:inLanguage

msg:inLanguage( lang )

#### mw.message:useDatabase

msg:useDatabase( bool )

#### mw.message:plain

msg:plain()

#### mw.message:exists

msg:exists()

#### mw.message:isBlank

msg:isBlank()

#### mw.message:isDisabled

msg:isDisabled()

### 站点信息库

#### mw.site.namespaces

• id：名字空间数字。
• name：本地名字空间名称。
• canonicalName：名字空间名字的规范形式。
• displayName：名字空间0的集合，用于显示的名字空间（因为这个名字通常是空白字符串）。
• hasSubpages：这个名字空间是否允许启用子页面（subpages）。
• hasGenderDistinction：这个名字空间在不同的词性是否有不同的别称（aliases）。
• isCapitalized：这个名字空间的页面的第一个字母是否会转化为大写。
• isContent：这个名字空间是否为内容名字空间。
• isIncludable：这个名字空间的页面是否可以被嵌入包含。
• isMovable：这个名字空间的页面是否可以移动。
• isSubject：这个名字空间是否为一个项目名字空间（subject namespace）。
• isTalk：这个名字空间是否为讨论页。
• defaultContentModel：这个名字空间的默认内容模型（字符串）。
• aliases：这个名字空间的别称的列表。
• subject：对应项目名字空间的数据。
• talk对应讨论页名字空间的数据。
• associated与之有关联的名字空间的数据。

#### mw.site.stats

• pages：wiki的页面数量。
• articles：wiki的文章数量。
• files：wiki的文件数量。
• edits：wiki的编辑次数。
• users：wiki的用户数量。
• activeUsers：wiki的活跃用户数量。

#### mw.site.stats.pagesInCategory

mw.site.stats.pagesInCategory( category, which )

• all：总共的页面、文件和子分类。
• subcats：子分类的数量。
• files：文件的数量。
• pages：页面的数量。

#### mw.site.stats.pagesInNamespace

mw.site.stats.pagesInNamespace( ns )

#### mw.site.stats.usersInGroup

mw.site.stats.usersInGroup( group )

#### mw.site.interwikiMap

mw.site.interwikiMap( filter )

• prefix——跨wiki前缀。
• url——跨wiki指向的URL。页面名称由参数$1体现。 • isProtocalRelative——布尔值，显示URL是否为URL • isLocal——这个URL是否是当前wiki的站点的。 • isCurrentWiki——这个URL是否是为当前wiki的。 • isTranscludable——使用这个跨wiki前缀的页面能否嵌入包含。这个要求scary transclusion，而这在维基媒体的wiki是禁用的。 • isExtraLanguageLink——跨wiki是否列举在了$wgExtraInterlanguageLinkPrefixes
• displayText——对于列举在$wgExtraInterlanguageLinkPrefixes中的链接，跨语言链接显示的文本。未指定时为nil。 • tooltip——对于列举在$wgExtraInterlanguageLinkPrefixes的链接，当用户悬浮在跨语言链接上时显示的浮窗提示文本。未指定时为nil。

### 文本库

#### mw.text.decode

mw.text.decode( s )
mw.text.decode( s, decodeNamedEntities )

#### mw.text.encode

mw.text.encode( s )
mw.text.encode( s, charset )

#### mw.text.jsonDecode

mw.text.jsonDecode( s )
mw.text.jsonDecode( s, flags )

• 如果数组含有null值，解析的JSON数组可能不是Lua序列。
• JSON对象会丢弃含有null值得键。
• 不能直接分辨带有序列整数键的是JSON数组还是JSON对象。
• 带有序列整数键从1开始的的JSON对象会被解析到作为有相同值的JSON数组的相同的表结构，尽管这些不一定总是相等，除非使用了mw.text.JSON_PRESERVE_KEYS

#### mw.text.jsonEncode

mw.text.jsonEncode( value )
mw.text.jsonEncode( value, flags )

• 空的表总是会被编码为空的数组（[]），而不是空的对象（{}）。
• 如果没有加入无效（dummy）元素，序列表不能被编码为JSON对象。
• 如果要产生带有nil值得对象，需要设置__pairs元方法。
• 带有从0开始的序列整数键的Lua表会被编码为JSON数组，带有从1开始的整数键的Lua表也是如此，除非使用了mw.text.JSON_PRESERVE_KEYS
• 如果同一个表中，既使用了数字，又使用了代表那个数字的字符串作为键，则行为未指定。

#### mw.text.killMarkers

mw.text.killMarkers( s )

#### mw.text.listToText

mw.text.listToText( list )
mw.text.listToText( list, separator, conjunction )

 -- 返回空字符串
mw.text.listToText( {} )

-- 返回"1"
mw.text.listToText( { 1 } )

-- 返回"1和2"（如果wiki的语言设置为“中文”，下同）
mw.text.listToText( { 1, 2 } )

-- 返回"1、2、3、4和5"
mw.text.listToText( { 1, 2, 3, 4, 5 } )

-- 返回"1; 2; 3; 4 or 5"
mw.text.listToText( { 1, 2, 3, 4, 5 }, '; ', ' or ' )


#### mw.text.nowiki

mw.text.nowiki( s )

• 以下字符：'"', '&', "'", '<', '=', '>', '[', ']', '{', '|', '}'
• 字符串开头或新行后面的的以下字符：'#', '*', ':', ';'、空格、制表符（'\t'）
• 空行会有关联的新行或返回转义的字符（Blank lines will have one of the associated newline or carriage return characters escaped）
• 字符串开始处或新行后的的"----"会使得第一个'-'被转义
• "__"会使一个下划线被转义
• "://"会使冒号被转义
• ISBN、RFC或PMID后的空白字符会被转义

#### mw.text.split

mw.text.split( s, pattern, plain )

#### mw.text.gsplit

mw.text.gsplit( s, pattern, plain )

#### mw.text.tag

mw.text.tag( name, attrs, content )
mw.text.tag{ name = string, attrs = table, content = string|false }

#### mw.text.trim

mw.text.trim( s )
mw.text.trim( s, charset )

#### mw.text.truncate

mw.text.truncate( text, length )
mw.text.truncate( text, length, ellipsis )
mw.text.truncate( text, length, ellipsis, adjustLength )

ellipsis的默认值取自wiki的内容语言的MediaWiki:ellipsis

-- 返回"foobarbaz"
mw.text.truncate( "foobarbaz", 9 )

-- 返回"fooba..."
mw.text.truncate( "foobarbaz", 5 )

-- 返回"...arbaz"
mw.text.truncate( "foobarbaz", -5 )

-- 返回"foo..."
mw.text.truncate( "foobarbaz", 6, nil, true )

-- 返回"foobarbaz"，因为比"foobarba..."更短
mw.text.truncate( "foobarbaz", 8 )


#### mw.text.unstripNoWiki

mw.text.unstripNoWiki( s )

#### mw.text.unstrip

mw.text.unstrip( s )

### 标题库

#### mw.title.equals

mw.title.equals( a, b )

#### mw.title.compare

mw.title.compare( a, b )

#### mw.title.getCurrentTitle

mw.title.getCurrentTitle()

#### mw.title.new

mw.title.new( text, namespace )
mw.title.new( id )

#### mw.title.makeTitle

mw.title.makeTitle( namespace, title, fragment, interwiki )

Creates a title object with title title in namespace namespace, optionally with the specified fragment and interwiki prefix. namespace may be any key found in mw.site.namespaces. If the resulting title is not valid, returns nil.

Note that, unlike mw.title.new(), this method will always apply the specified namespace. For example, mw.title.makeTitle( 'Template', 'Module:Foo' ) will create an object for the page Template:Module:Foo, while mw.title.new( 'Module:Foo', 'Template' ) will create an object for the page Module:Foo.

#### 页面标题对象

A title object has a number of properties and methods. Most of the properties are read-only.

Note that fields ending with text return titles as string values whereas the fields ending with title return title objects.

• id: The page_id. 0 if the page does not exist. This may be expensive.
• interwiki: The interwiki prefix, or the empty string if none.
• namespace: The namespace number.
• fragment: The fragment, or the empty string. May be assigned.
• nsText: The text of the namespace for the page.
• subjectNsText: The text of the subject namespace for the page.
• text: The title of the page, without the namespace or interwiki prefixes.
• prefixedText: The title of the page, with the namespace and interwiki prefixes.
• fullText: The title of the page, with the namespace and interwiki prefixes and the fragment. Interwiki is not returned if equal to the current.
• rootText: If this is a subpage, the title of the root page without prefixes. Otherwise, the same as title.text.
• baseText: If this is a subpage, the title of the page it is a subpage of without prefixes. Otherwise, the same as title.text.
• subpageText: If this is a subpage, just the subpage name. Otherwise, the same as title.text.
• canTalk: Whether the page for this title could have a talk page.
• exists: Whether the page exists. Alias for file.exists for Media-namespace titles. For File-namespace titles this checks the existence of the file description page, not the file itself. This may be expensive.
• file, fileExists: See #File metadata below.
• isContentPage: Whether this title is in a content namespace.
• isExternal: Whether this title has an interwiki prefix.
• isLocal: Whether this title is in this project. For example, on the English Wikipedia, any other Wikipedia is considered "local" while Wiktionary and such are not.
• isRedirect: Whether this is the title for a page that is a redirect. This may be expensive.
• isSpecialPage: Whether this is the title for a possible special page (i.e. a page in the Special: namespace).
• isSubpage: Whether this title is a subpage of some other title.
• isTalkPage: Whether this is a title for a talk page.
• isSubpageOf( title2 ): Whether this title is a subpage of the given title.
• inNamespace( ns ): Whether this title is in the given namespace. Namespaces may be specified by anything that is a key found in mw.site.namespaces.
• inNamespaces( ... ): Whether this title is in any of the given namespaces. Namespaces may be specified by anything that is a key found in mw.site.namespaces.
• hasSubjectNamespace( ns ): Whether this title's subject namespace is in the given namespace. Namespaces may be specified by anything that is a key found in mw.site.namespaces.
• contentModel: The content model for this title, as a string. This may be expensive.
• basePageTitle: The same as mw.title.makeTitle( title.namespace, title.baseText ).
• rootPageTitle: The same as mw.title.makeTitle( title.namespace, title.rootText ).
• talkPageTitle: The same as mw.title.makeTitle( mw.site.namespaces[title.namespace].talk.id, title.text ), or nil if this title cannot have a talk page.
• subjectPageTitle: The same as mw.title.makeTitle( mw.site.namespaces[title.namespace].subject.id, title.text ).
• redirectTarget: Returns a title object of the target of the redirect page if the page is a redirect and the page exists, returns false otherwise.
• protectionLevels: The page's protection levels. This is a table with keys corresponding to each action (e.g., "edit" and "move"). The table values are arrays, the first item of which is a string containing the protection level. If the page is unprotected, either the table values or the array items will be nil. This is expensive.
• cascadingProtection: The cascading protections applicable to the page. This is a table with keys "restrictions" (itself a table with keys like protectionLevels has) and "sources" (an array listing titles where the protections cascade from). If no protections cascade to the page, "restrictions" and "sources" will be empty. This is expensive.
• subPageTitle( text ): The same as mw.title.makeTitle( title.namespace, title.text .. '/' .. text ).
• partialUrl(): Returns title.text encoded as it would be in a URL.
• fullUrl( query, proto ): Returns the full URL (with optional query table/string) for this title. proto may be specified to control the scheme of the resulting url: "http", "https", "relative" (the default), or "canonical".
• localUrl( query ): Returns the local URL (with optional query table/string) for this title.
• canonicalUrl( query ): Returns the canonical URL (with optional query table/string) for this title.
• getContent(): Returns the (unparsed) content of the page, or nil if there is no page. The page will be recorded as a transclusion.

Title objects may be compared using relational operators. tostring( title ) will return title.prefixedText.

Since people find the fact surprising, note that accessing any expensive field on a title object records a "link" to the page (as shown on Special:WhatLinksHere, for example). Using the title object's getContent() method or accessing the redirectTarget field records it as a "嵌入", and accessing the title object's file or fileExists fields records it as a "文件链接".

##### 文件元数据

Title objects representing a page in the File or Media namespace will have a property called file. This is expensive. This is a table, structured as follows:

• exists: Whether the file exists. It will be recorded as an image usage. The fileExists property on a Title object exists for backwards compatibility reasons and is an alias for this property. If this is false, all other file properties will be nil.
• width: The width of the file. If the file contains multiple pages, this is the width of the first page.
• height: The height of the file. If the file contains multiple pages, this is the height of the first page.
• pages: If the file format supports multiple pages, this is a table containing tables for each page of the file; otherwise, it is nil. The # operator can be used to get the number of pages in the file. Each individual page table contains a width and height property.
• size: The size of the file in bytes.
• mimeType: The MIME type of the file.
##### 高开销属性

The properties id, isRedirect, exists, and contentModel require fetching data about the title from the database. For this reason, the expensive function count is incremented the first time one of them is accessed for a page other than the current page. Subsequent accesses of any of these properties for that page will not increment the expensive function count again.

Other properties marked as expensive will always increment the expensive function count the first time they are accessed for a page other than the current page.

### URI库

#### mw.uri.encode

mw.uri.encode( s, enctype )

Percent-encodes the string. The default type, "QUERY", encodes spaces using '+' for use in query strings; "PATH" encodes spaces as %20; and "WIKI" encodes spaces as '_'.

Note that the "WIKI" format is not entirely reversible, as both spaces and underscores are encoded as '_'.

#### mw.uri.decode

mw.uri.decode( s, enctype )

Percent-decodes the string. The default type, "QUERY", decodes '+' to space; "PATH" does not perform any extra decoding; and "WIKI" decodes '_' to space.

#### mw.uri.anchorEncode

mw.uri.anchorEncode( s )

Encodes a string for use in a MediaWiki URI fragment.

#### mw.uri.buildQueryString

mw.uri.buildQueryString( table )

Encodes a table as a URI query string. Keys should be strings; values may be strings or numbers, sequence tables, or boolean false.

#### mw.uri.parseQueryString

mw.uri.parseQueryString( s, i, j )

Decodes the query string s to a table. Keys in the string without values will have a value of false; keys repeated multiple times will have sequence tables as values; and others will have strings as values.

The optional numerical arguments i and j can be used to specify a substring of s to be parsed, rather than the entire string. i is the position of the first character of the substring, and defaults to 1. j is the position of the last character of the substring, and defaults to the length of the string. Both i and j can be negative, as in string.sub.

#### mw.uri.canonicalUrl

mw.uri.canonicalUrl( page, query )

Returns a URI object for the canonical URL for a page, with optional query string/table.

#### mw.uri.fullUrl

mw.uri.fullUrl( page, query )

Returns a URI object for the full URL for a page, with optional query string/table.

#### mw.uri.localUrl

mw.uri.localUrl( page, query )

Returns a URI object for the local URL for a page, with optional query string/table.

#### mw.uri.new

mw.uri.new( s )

Constructs a new URI object for the passed string or table. See the description of URI objects for the possible fields for the table.

#### mw.uri.validate

mw.uri.validate( table )

Validates the passed table (or URI object). Returns a boolean indicating whether the table was valid, and on failure a string explaining what problems were found.

#### URI对象

URI对象有以下域，其中的部分或全部可能是nil：

• protocol: String protocol/scheme
• user: String user
• host: String host name
• port: Integer port
• path: String path
• query: A table, as from mw.uri.parseQueryString
• fragment: String fragment.

The following properties are also available:

• userInfo: String user and password
• hostPort: String host and port
• authority: String user, password, host, and port
• queryString: String version of the query table
• relativePath: String path, query string, and fragment

tostring() will give the URI string.

Methods of the URI object are:

##### mw.uri:parse

uri:parse( s )

Parses a string into the current URI object. Any fields specified in the string will be replaced in the current object; fields not specified will keep their old values.

##### mw.uri:clone

uri:clone()

Makes a copy of the URI object.

##### mw.uri:extend

uri:extend( parameters )

Merges the parameters table into the object's query table.

### Ustring库

The ustring library is intended to be a direct reimplementation of the standard String library, except that the methods operate on characters in UTF-8 encoded strings rather than bytes.

Most functions will raise an error if the string is not valid UTF-8; exceptions are noted.

#### mw.ustring.maxPatternLength

The maximum allowed length of a pattern, in bytes.

#### mw.ustring.maxStringLength

The maximum allowed length of a string, in bytes.

#### mw.ustring.byte

mw.ustring.byte( s, i, j )

Returns individual bytes; identical to string.byte().

#### mw.ustring.byteoffset

mw.ustring.byteoffset( s, l, i )

Returns the byte offset of a character in the string. The default for both l and i is 1. i may be negative, in which case it counts from the end of the string.

The character at l == 1 is the first character starting at or after byte i; the character at l == 0 is the first character starting at or before byte i. Note this may be the same character. Greater or lesser values of l are calculated relative to these.

#### mw.ustring.char

mw.ustring.char( ... )

Much like string.char(), except that the integers are Unicode codepoints rather than byte values.

local value = mw.ustring.char( 0x41f, 0x440, 0x438, 0x432, 0x435, 0x442, 0x21 ) -- value is now 'Привет!'


#### mw.ustring.codepoint

mw.ustring.codepoint( s, i, j )

Much like string.byte(), except that the return values are codepoints and the offsets are characters rather than bytes.

#### mw.ustring.find

mw.ustring.find( s, pattern, init, plain )

Much like string.find(), except that the pattern is extended as described in Ustring patterns and the init offset is in characters rather than bytes.

#### mw.ustring.format

mw.ustring.format( format, ... )

Identical to string.format(). Widths and precisions for strings are expressed in bytes, not codepoints.

#### mw.ustring.gcodepoint

mw.ustring.gcodepoint( s, i, j )

Returns three values for iterating over the codepoints in the string. i defaults to 1, and j to -1. This is intended for use in the iterator form of for:

for codepoint in mw.ustring.gcodepoint( s ) do
-- 语句块
end


#### mw.ustring.gmatch

mw.ustring.gmatch( s, pattern )

Much like string.gmatch(), except that the pattern is extended as described in Ustring patterns.

#### mw.ustring.gsub

mw.ustring.gsub( s, pattern, repl, n )

Much like string.gsub(), except that the pattern is extended as described in Ustring patterns.

#### mw.ustring.isutf8

mw.ustring.isutf8( s )

Returns true if the string is valid UTF-8, false if not.

#### mw.ustring.len

mw.ustring.len( s )

Returns the length of the string in codepoints, or nil if the string is not valid UTF-8.

See string.len() for a similar function that uses byte length rather than codepoints.

#### mw.ustring.lower

mw.ustring.lower( s )

Much like string.lower(), except that all characters with lowercase to uppercase definitions in Unicode are converted.

If the Language library is also loaded, this will instead call lc() on the default language object.

#### mw.ustring.match

mw.ustring.match( s, pattern, init )

Much like string.match(), except that the pattern is extended as described in Ustring patterns and the init offset is in characters rather than bytes.

#### mw.ustring.rep

mw.ustring.rep( s, n )

#### mw.ustring.sub

mw.ustring.sub( s, i, j )

Much like string.sub(), except that the offsets are characters rather than bytes.

#### mw.ustring.toNFC

mw.ustring.toNFC( s )

Converts the string to Normalization Form C. Returns nil if the string is not valid UTF-8.

#### mw.ustring.toNFD

mw.ustring.toNFD( s )

Converts the string to Normalization Form D. Returns nil if the string is not valid UTF-8.

#### mw.ustring.upper

mw.ustring.upper( s )

Much like string.upper(), except that all characters with uppercase to lowercase definitions in Unicode are converted.

If the Language library is also loaded, this will instead call uc() on the default language object.

#### Ustring模式

Patterns in the ustring functions use the same syntax as the String library patterns. The major difference is that the character classes are redefined in terms of Unicode character properties:

• %a: represents all characters with General Category "Letter".
• %c: represents all characters with General Category "Control".
• %d: represents all characters with General Category "Number, decimal digit".
• %l: represents all characters with General Category "Lowercase Letter".
• %p: represents all characters with General Category "Punctuation".
• %s: represents all characters with General Category "Separator", plus tab, linefeed, carriage return, vertical tab, and form feed.
• %u: represents all characters with General Category "Uppercase Letter".
• %w: represents all characters with General Category "Letter" or "Decimal Number".
• %x: adds fullwidth character versions of the hex digits.

Like in String library patterns, %A, %C, %D, %L, %P, %S, %U和⧼word-separator⧽%W here represent the complementary set ("all characters without given General Category").

In all cases, characters are interpreted as Unicode characters instead of bytes, so ranges such as [０-９], patterns such as %b«», and quantifiers applied to multibyte characters will work correctly. Empty captures will capture the position in code points rather than bytes.

## 可加载的库

These libraries are not included by default, but if needed may be loaded using require().

### bit32

This emulation of the Lua 5.2 bit32 library may be loaded using

bit32 = require( 'bit32' )


The bit32 library provides bitwise operations on unsigned 32-bit integers. Input numbers are truncated to integers (in an unspecified manner) and reduced modulo 232 so the value is in the range 0 to 232−1; return values are also in this range.

When bits are numbered (as in bit32.extract()), 0 is the least-significant bit (the one with value 20) and 31 is the most-significant (the one with value 231).

#### bit32.band

bit32.band( ... )

Returns the bitwise AND of its arguments: the result has a bit set only if that bit is set in all of the arguments.

If given zero arguments, the result has all bits set.

#### bit32.bnot

bit32.bnot( x )

Returns the bitwise complement of x.

#### bit32.bor

bit32.bor( ... )

Returns the bitwise OR of its arguments: the result has a bit set if that bit is set in any of the arguments.

If given zero arguments, the result has all bits clear.

#### bit32.btest

bit32.btest( ... )

Equivalent to bit32.band( ... ) ~= 0

#### bit32.bxor

bit32.bxor( ... )

Returns the bitwise XOR of its arguments: the result has a bit set if that bit is set in an odd number of the arguments.

If given zero arguments, the result has all bits clear.

#### bit32.extract

bit32.extract( n, field, width )

Extracts width bits from n, starting with bit field. Accessing bits outside of the range 0 to 31 is an error.

If not specified, the default for width is 1.

#### bit32.replace

bit32.replace( n, v, field, width )

Replaces width bits in n, starting with bit field, with the low width bits from v. Accessing bits outside of the range 0 to 31 is an error.

If not specified, the default for width is 1.

#### bit32.lshift

bit32.lshift( n, disp )

Returns the number n shifted disp bits to the left. This is a logical shift: inserted bits are 0. This is generally equivalent to multiplying by 2disp.

Note that a displacement over 31 will result in 0.

#### bit32.rshift

bit32.rshift( n, disp )

Returns the number n shifted disp bits to the right. This is a logical shift: inserted bits are 0. This is generally equivalent to dividing by 2disp.

Note that a displacement over 31 will result in 0.

#### bit32.arshift

bit32.arshift( n, disp )

Returns the number n shifted disp bits to the right. This is an arithmetic shift: if disp is positive, the inserted bits will be the same as bit 31 in the original number.

Note that a displacement over 31 will result in 0 or 4294967295.

#### bit32.lrotate

bit32.lrotate( n, disp )

Returns the number n rotated disp bits to the left.

Note that rotations are equivalent modulo 32: a rotation of 32 is the same as a rotation of 0, 33 is the same as 1, and so on.

#### bit32.rrotate

bit32.rrotate( n, disp )

Returns the number n rotated disp bits to the right.

Note that rotations are equivalent modulo 32: a rotation of 32 is the same as a rotation of 0, 33 is the same as 1, and so on.

### libraryUtil

This library contains methods useful when implementing Scribunto libraries. It may be loaded using

libraryUtil = require( 'libraryUtil' )


#### libraryUtil.checkType

libraryUtil.checkType( name, argIdx, arg, expectType, nilOk )

Raises an error if type( arg ) does not match expectType. In addition, no error will be raised if arg is nil and nilOk is true.

name is the name of the calling function, and argIdx is the position of the argument in the argument list. These are used in formatting the error message.

#### libraryUtil.checkTypeMulti

libraryUtil.checkTypeMulti( name, argIdx, arg, expectTypes )

Raises an error if type( arg ) does not match any of the strings in the array expectTypes.

This is for arguments that have more than one valid type.

#### libraryUtil.checkTypeForIndex

libraryUtil.checkTypeForIndex( index, value, expectType )

Raises an error if type( value ) does not match expectType.

This is intended for use in implementing a __newindex metamethod.

#### libraryUtil.checkTypeForNamedArg

libraryUtil.checkTypeForNamedArg( name, argName, arg, expectType, nilOk )

Raises an error if type( arg ) does not match expectType. In addition, no error will be raised if arg is nil and nilOk is true.

This is intended to be used as an equivalent to libraryUtil.checkType() in methods called using Lua's "named argument" syntax, func{ name = value }.

#### libraryUtil.makeCheckSelfFunction

libraryUtil.makeCheckSelfFunction( libraryName, varName, selfObj, selfObjDesc )

This is intended for use in implementing "methods" on object tables that are intended to be called with the obj:method() syntax. It returns a function that should be called at the top of these methods with the self argument and the method name, which will raise an error if that self object is not selfObj.

This function will generally be used in a library's constructor function, something like this:

 function myLibrary.new()
local obj = {}
local checkSelf = libraryUtil.makeCheckSelfFunction( 'myLibrary', 'obj', obj, 'myLibrary object' )

function obj:method()
checkSelf( self, 'method' )
end

function obj:method2()
checkSelf( self, 'method2' )
end

return obj
end


### luabit

The luabit library modules "bit" and "hex" may be loaded using

bit = require( 'luabit.bit' )
hex = require( 'luabit.hex' )


Note that the bit32 library contains the same operations as "luabit.bit", and the operations in "luabit.hex" may be performed using string.format() and tonumber().

The luabit module "noki" is not available, as it is entirely useless in Scribunto. The luabit module "utf8" is also not available, as it was considered redundant to the Ustring library.

### ustring

The pure-Lua backend to the Ustring library may be loaded using

ustring = require( 'ustring' )


In all cases the Ustring library (mw.ustring) should be used instead, as that replaces many of the slower and more memory-intensive operations with callbacks into PHP code.

## 扩展库

Some MediaWiki extensions provide additional Scribunto libraries. These are also located in the table mw, usually in the table mw.ext, however, they are only present when certain extensions are installed (in addition to the Scribunto extension itself).

Such extensions use Scribunto provided hooks:

Writing Scribunto libraries provides information on how such libraries can be developed to provide Lua interfaces for MediaWiki extensions.

The following libraries are planned, or are in Gerrit pending review.

• (none at this time)

### mw.wikibase

Wikibase Client provides access to localizable structured data. See Extension:Wikibase Client/Lua. This is supported by Wikidata.

### mw.wikibase.lexeme

WikibaseLexeme provides access to Wikibase Lexeme entities. This is supported by Wikidata:Lexicographical data.

### mw.wikibase.mediainfo

WikibaseMediaInfo provides access to Wikibase MediaInfo entities. See Extension:WikibaseMediaInfo/Lua. This is supported by Structured Data on Commons. See Commons:Structured data/Lua.

### mw.bcmath

BCmath provides arbitrary-precision arithmetic to Lua modules. See BCmath documentation via "LDoc" link at Extension:BCmath#Usage.

### mw.smw

Semantic Scribunto provides native support for the Scribunto extension to Semantic MediaWiki extension.

### mw.ext.data

JsonConfig provides access to localizable tabular and map data. See Extension:JsonConfig/Tabular. Tabular Data and GeoJSON Map Data is supported in Commons "Data:" namespace.

### mw.ext.cargo

Cargo provides a means to query its data store from Lua. See Extension:Cargo/Other features#Lua support.

### mw.ext.cattools

CategoryToolbox provides a means to check from Lua if a certain page belongs to a category

### mw.ext.FlaggedRevs

FlaggedRevs provides a means to access the stability settings of a page from Lua.

### mw.ext.TitleBlacklist

TitleBlacklist provides a means to test and obtain information about blacklisted page naming entries from Lua.

### mw.ext.ParserFunctions

ParserFunctions provides a means to evaluate a parser function expressions from Lua.

### mw.ext.articlePlaceholder

ArticlePlaceholder provides a means to override default Wikibase renderings from Lua. See Extension:ArticlePlaceholder/Module:AboutTopic.

## 与标准Lua的不同之处

### 改变的函数

The following functions have been modified:

setfenv()
getfenv()
May not be available, depending on the configuration. If available, attempts to access parent environments will fail.
getmetatable()
tostring()
Pointer addresses of tables and functions are not provided. This is to make memory corruption vulnerabilities more difficult to exploit.
pairs()
ipairs()
Support for the __pairs and __ipairs metamethods (added in Lua 5.2) has been added.
pcall()
xpcall()
Certain internal errors cannot be intercepted.
require()
Can fetch certain built-in modules distributed with Scribunto, as well as modules present in the Module namespace of the wiki. To fetch wiki modules, use the full page name including the namespace. Cannot otherwise access the local filesystem.

### Removed functions and packages

The following packages are mostly removed. Only those functions listed are available:

package.*
Filesystem and C library access has been removed. Available functions and tables are:
package.seeall()
os.*
There are some insecure functions in here, such as os.execute(), which can't be allowed. Available functions are:
os.clock()
os.date()
os.difftime()
os.time()
debug.*
Most of the functions are insecure. Available functions are:
debug.traceback()

The following functions and packages are not available:

collectgarbage()
module()
coroutine.*
No application is known for us, so it has not been reviewed for security.
dofile()
io.*, file.*
Allows local filesystem access, which is insecure.
These were omitted to allow for static analysis of the Lua source code. Also, allowing these would allow Lua code to be added directly to article and template pages, which was not desired for usability reasons.
print()
This was discussed on wikitech-l and it was decided that it should be omitted in favour of return values, to improve code quality. If necessary, mw.log() may be used to output information to the debug console.
string.dump()
May expose private data from parent environments.

Referential data structures
Circular data structures and data structures where the same node may be reached by more than one path cannot be correctly sent to PHP. Attempting to do so will cause undefined behavior. This includes (but is not limited to) returning such data structures from the module called by {{#invoke:}} and passing such data structures as parameters to Scribunto library functions that are implemented as callbacks into PHP.

Such data structures may be used freely within Lua, including as the return values of modules loaded with mw.loadData().

## Writing Scribunto libraries

This information is useful to developers writing additional Scribunto libraries, whether for inclusion in Scribunto itself or for providing an interface for their own extensions.

A Scribunto library will generally consist of five parts:

• The PHP portion of the library.
• The Lua portion of the library.
• The PHP portion of the test cases.
• The Lua portion of the test cases.
• The documentation.

Existing libraries serve as a good example.

The PHP portion of the library is a class that must extend Scribunto_LuaLibraryBase. See the documentation for that class for implementation details. In the Scribunto extension, this file should be placed in engines/LuaCommon/NameLibrary.php, and a mapping added to Scribunto_LuaEngine::$libraryClasses. Other extensions should use the ScribuntoExternalLibraries hook. In either case, the key should match the Lua module name ("mw.name" for libraries in Scribunto, or "mw.ext.name" for extension libraries). The Lua portion of the library sets up the table containing the functions that can be called from Lua modules. In the Scribunto extension, the file should be placed in engines/LuaCommon/lualib/mw.name.lua. This file should generally include boilerplate something like this: local object = {} local php function object.setupInterface( options ) -- Remove setup function object.setupInterface = nil -- Copy the PHP callbacks to a local variable, and remove the global php = mw_interface mw_interface = nil -- Do any other setup here -- Install into the mw global mw = mw or {} mw.ext = mw.ext or {} mw.ext.NAME = object -- Indicate that we're loaded package.loaded['mw.ext.NAME'] = object end return object  The module in engines/LuaCommon/lualib/libraryUtil.lua (load this with local util = require 'libraryUtil') contains some functions that may be helpful. Be sure to run the Scribunto test cases with your library loaded, even if your library doesn't itself provide any test cases. The standard test cases include tests for things like libraries adding unexpected global variables. Also, if the library is loaded with PHP, any upvalues that its Lua functions have will not be reset between #invoke's. Care must be taken to ensure that modules can't abuse this to transfer information between #invoke's. ### Test cases The Scribunto extension includes a base class for test cases, Scribunto_LuaEngineTestBase, which will run the tests against both the LuaSandbox and LuaStandalone engines. The library's test case should extend this class, and should not override static function suite(). In the Scribunto extension, the test case should be in tests/engines/LuaCommon/NameLibraryTest.php and added to the array in ScribuntoHooks::unitTestsList() (in common/Hooks.php); extensions should add the test case in their own UnitTestsList hook function, probably conditional on whether $wgAutoloadClasses['Scribunto_LuaEngineTestBase'] is set.

Most of the time, all that is needed to make the test case is this:

class ClassNameTest extends Scribunto_LuaEngineTestBase {
protected static $moduleName = 'ClassNameTest'; function getTestModules() { return parent::getTestModules() + array( 'ClassNameTest' => __DIR__ . '/ClassNameTests.lua'; ); } }  This will load the file ClassNameTests.lua as if it were the page "Module:ClassNameTests", expecting it to return an object with the following properties: • count: Integer, number of tests • provide( n ): Function that returns three values: n, the name of test n, and a string that is the expected output for test n. • run( n ): Function that runs test n and returns one string. If getTestModules() is declared as shown, "Module:TestFramework" is available which provides many useful helper methods. If this is used, ClassNameTests.lua would look something like this: local testframework = require 'Module:TestFramework' return testframework.getTestProvider( { -- Tests go here } )  Each test is itself a table, with the following properties: • name: The name of the test. • func: The function to execute. • args: Optional table of arguments to pass to the function. • expect: Results to expect. • type: Optional "type" of the test, default is "Normal". The type controls the format of expect and how func is called. Included types are: • Normal: expect is a table of return values, or a string if the test should raise an error. func is simply called. • Iterator: expect is a table of tables of return values. func is called as with an iterated for loop, and each iteration's return values are accumulated. • ToString: Like "Normal", except each return value is passed through tostring(). #### 在其他扩展中的测试样例 There are (at least) two ways to run PHPUnit tests: 1. Run phpunit against core, allowing the tests/phpunit/suites/ExtensionsTestSuite.php to find the extension's tests using the UnitTestsList hook. If your extension's test class names all contain a unique component (e.g. the extension's name), the --filter option may be used to run only your extension's tests. 2. Run phpunit against the extension directory, where it will pick up any file ending in "Test.php". Either of these will work fine if Scribunto is loaded in LocalSettings.php. And it is easy for method #1 to work if Scribunto is not loaded, as the UnitTestsList hook can easily be written to avoid returning the Scribunto test when $wgAutoloadClasses['Scribunto_LuaEngineTestBase'] is not set.

But Jenkins uses method #2. For Jenkins to properly run the tests, you will need to add Scribunto as a dependency for your extension. See Gerrit change 56570 for an example of how this is done.

If for some reason you need the tests to be able to run using method #2 without Scribunto loaded, one workaround is to add this check to the top of your unit test file:

 if ( !isset( \$GLOBALS['wgAutoloadClasses']['Scribunto_LuaEngineTestBase'] ) ) {
return;
}


### 文档

Modules included in Scribunto should include documentation in the Scribunto libraries section above. Extension libraries should include documentation in a subpage of their own extension page, and link to that documentation from the Extension libraries subsection above.

## 许可

This manual is derived from the Lua 5.1 reference manual, which is available under the MIT license.

This derivative manual may also be copied under the terms of the same license.