path: root/docs
diff options
authorPierre Schmitz <>2014-12-27 15:41:37 +0100
committerPierre Schmitz <>2014-12-31 11:43:28 +0100
commitc1f9b1f7b1b77776192048005dcc66dcf3df2bfb (patch)
tree2b38796e738dd74cb42ecd9bfd151803108386bc /docs
parentb88ab0086858470dd1f644e64cb4e4f62bb2be9b (diff)
Update to MediaWiki 1.24.1
Diffstat (limited to 'docs')
24 files changed, 1210 insertions, 179 deletions
diff --git a/docs/README b/docs/README
index 69170767..5bc8bfc6 100644
--- a/docs/README
+++ b/docs/README
@@ -1,16 +1,19 @@
-[July 22nd 2008]
+/docs Directory README
The 'docs' directory contain various text files that should help you understand
the most important parts of the code of MediaWiki. More in-depth documentation
-can be found at
+can be found at:
API documentation is automatically generated and updated daily at:
You can get a fresh version using 'make doc' or mwdocgen.php in the
../maintenance/ directory.
-For end user / administrators, most of the documentation is located online at:
+For end users, most of the documentation is located online at:
+Documentation for MediaWiki site administrators is at:
diff --git a/docs/contenthandler.txt b/docs/contenthandler.txt
index 899554af..3f0fca21 100644
--- a/docs/contenthandler.txt
+++ b/docs/contenthandler.txt
@@ -18,7 +18,7 @@ ContentHandler::getDefaultModelFor($title) as follows:
* The global setting $wgNamespaceContentModels specifies a content model for the given namespace.
* The hook ContentHandlerDefaultModelFor may be used to override the page's default model.
-* Pages in NS_MEDIAWIKI and NS_USER default to the CSS or JavaScript model if they end in .js or .css, respectively.
+* Pages in NS_MEDIAWIKI and NS_USER default to the CSS or JavaScript model if they end in .css or .js, respectively.
Pages in NS_MEDIAWIKI default to the wikitext model otherwise.
* The hook TitleIsCssOrJsPage may be used to force a page to use the CSS or JavaScript model.
This is a compatibility feature. The ContentHandlerDefaultModelFor hook should be used instead if possible.
diff --git a/docs/database.txt b/docs/database.txt
index 65a597b3..735f26bf 100644
--- a/docs/database.txt
+++ b/docs/database.txt
@@ -7,7 +7,7 @@ By Tim Starling, January 2006.
For information about the MediaWiki database layout, such as a
description of the tables and their contents, please see:
diff --git a/docs/design.txt b/docs/design.txt
index f95ef0f6..5c04adde 100644
--- a/docs/design.txt
+++ b/docs/design.txt
@@ -3,7 +3,7 @@ design.txt
This is a brief overview of the new design.
More thorough and up-to-date information is available on the documentation
-wiki at
+wiki at
Primary classes:
diff --git a/docs/distributors.txt b/docs/distributors.txt
index 4a654315..efa573db 100644
--- a/docs/distributors.txt
+++ b/docs/distributors.txt
@@ -52,7 +52,7 @@ root, is /w (so, e.g., /var/www/w). Rewrite rules can then be used to enable
is the convention Wikipedia uses.) In theory, it should be possible to enable
the appropriate rewrite rules by default, if you can reconfigure the web
server, but you'd need to alter LocalSettings.php too. See
-<> for details on short URLs.
+<> for details on short URLs.
If you really must mess around with the directory structure, note that the
following files *must* all be web-accessible for MediaWiki to function
@@ -122,7 +122,7 @@ needed to rename LocalSettings.php in order to upgrade using the installer).
== Documentation ==
MediaWiki's official documentation is split between two places: the source
-code, and <>. The source code documentation is written
+code, and <>. The source code documentation is written
exclusively by developers, and so is likely to be reliable (at worst,
outdated). However, it can be pretty sparse. documentation is
often much more thorough, but it's maintained by a wiki that's open to
@@ -135,7 +135,7 @@ MediaWiki is a project hosted and led by the Wikimedia Foundation, the
not-for-profit charity that operates Wikipedia. Wikimedia employs the lead
developer and several other paid developers, but commit access is given out
liberally and there are multiple very active volunteer developers as well. A
-list of developers can be found at <>.
+list of developers can be found at <>.
MediaWiki's bug tracker is at <>. However, most
developers follow the bug tracker little or not at all. The best place to
@@ -179,7 +179,7 @@ perhaps configure it to use them (see Configuration section of this document):
* Squid: Can provide a drastic speedup and a major cut in resource
consumption, but enabling it may interfere with other applications. It might
be suitable for a separate mediawiki-squid package. For setup details, see:
- <>
+ <>
* rsvg or other SVG rasterizer: ImageMagick can be used for SVG support, but
is not ideal. Wikipedia (as of the time of this writing) uses rsvg. To
enable, set "$wgSVGConverter = 'rsvg';" (or other as appropriate).
diff --git a/docs/export-0.9.xsd b/docs/export-0.9.xsd
new file mode 100644
index 00000000..d5e7b99a
--- /dev/null
+++ b/docs/export-0.9.xsd
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+ This is an XML Schema description of the format
+ output by MediaWiki's Special:Export system.
+ Version 0.2 adds optional basic file upload info support,
+ which is used by our OAI export/import submodule.
+ Version 0.3 adds some site configuration information such
+ as a list of defined namespaces.
+ Version 0.4 adds per-revision delete flags, log exports,
+ discussion threading data, a per-page redirect flag, and
+ per-namespace capitalization.
+ Version 0.5 adds byte count per revision.
+ Version 0.6 adds a separate namespace tag, and resolves the
+ redirect target and adds a separate sha1 tag for each revision.
+ Version 0.7 adds a unique identity constraint for both page and
+ revision identifiers. See also bug 4220.
+ Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
+ Moves <logitem> to its right location.
+ Add parentid to revision.
+ Fix type for <id> within <contributor> to "nonNegativeInteger"
+ Version 0.8 adds support for a <model> and a <format> tag for
+ each revision. See contenthandler.txt.
+ Version 0.9 adds the database name to the site information.
+ The canonical URL to the schema document is:
+ Use the namespace:
+<schema xmlns=""
+ xmlns:mw=""
+ targetNamespace=""
+ elementFormDefault="qualified">
+ <annotation>
+ <documentation xml:lang="en">
+ MediaWiki's page export format
+ </documentation>
+ </annotation>
+ <!-- Need this to reference xml:lang -->
+ <import namespace=""
+ schemaLocation="" />
+ <!-- Our root element -->
+ <element name="mediawiki" type="mw:MediaWikiType">
+ <!-- Page ID contraint, see bug 4220 -->
+ <unique name="PageIDConstraint">
+ <selector xpath="mw:page" />
+ <field xpath="mw:id" />
+ </unique>
+ <!-- Revision ID contraint, see bug 4220 -->
+ <unique name="RevIDConstraint">
+ <selector xpath="mw:page/mw:revision" />
+ <field xpath="mw:id" />
+ </unique>
+ </element>
+ <complexType name="MediaWikiType">
+ <sequence>
+ <element name="siteinfo" type="mw:SiteInfoType"
+ minOccurs="0" maxOccurs="1" />
+ <element name="page" type="mw:PageType"
+ minOccurs="0" maxOccurs="unbounded" />
+ <element name="logitem" type="mw:LogItemType"
+ minOccurs="0" maxOccurs="unbounded" />
+ </sequence>
+ <attribute name="version" type="string" use="required" />
+ <attribute ref="xml:lang" use="required" />
+ </complexType>
+ <complexType name="SiteInfoType">
+ <sequence>
+ <element name="sitename" type="string" minOccurs="0" />
+ <element name="dbname" type="string" minOccurs="0" />
+ <element name="base" type="anyURI" minOccurs="0" />
+ <element name="generator" type="string" minOccurs="0" />
+ <element name="case" type="mw:CaseType" minOccurs="0" />
+ <element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
+ </sequence>
+ </complexType>
+ <simpleType name="CaseType">
+ <restriction base="NMTOKEN">
+ <!-- Cannot have two titles differing only by case of first letter. -->
+ <!-- Default behavior through 1.5, $wgCapitalLinks = true -->
+ <enumeration value="first-letter" />
+ <!-- Complete title is case-sensitive -->
+ <!-- Behavior when $wgCapitalLinks = false -->
+ <enumeration value="case-sensitive" />
+ <!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
+ <!-- Not yet implemented as of MediaWiki 1.18 -->
+ <enumeration value="case-insensitive" />
+ </restriction>
+ </simpleType>
+ <simpleType name="DeletedFlagType">
+ <restriction base="NMTOKEN">
+ <enumeration value="deleted" />
+ </restriction>
+ </simpleType>
+ <complexType name="NamespacesType">
+ <sequence>
+ <element name="namespace" type="mw:NamespaceType"
+ minOccurs="0" maxOccurs="unbounded" />
+ </sequence>
+ </complexType>
+ <complexType name="NamespaceType">
+ <simpleContent>
+ <extension base="string">
+ <attribute name="key" type="integer" />
+ <attribute name="case" type="mw:CaseType" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <complexType name="RedirectType">
+ <simpleContent>
+ <extension base="string">
+ <attribute name="title" type="string" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <simpleType name="ContentModelType">
+ <restriction base="string">
+ <pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
+ </restriction>
+ </simpleType>
+ <simpleType name="ContentFormatType">
+ <restriction base="string">
+ <pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
+ </restriction>
+ </simpleType>
+ <complexType name="PageType">
+ <sequence>
+ <!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
+ <element name="title" type="string" />
+ <!-- Namespace in canonical form -->
+ <element name="ns" type="nonNegativeInteger" />
+ <!-- optional page ID number -->
+ <element name="id" type="positiveInteger" />
+ <!-- flag if the current revision is a redirect -->
+ <element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
+ <!-- comma-separated list of string tokens, if present -->
+ <element name="restrictions" type="string" minOccurs="0" />
+ <!-- Zero or more sets of revision or upload data -->
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element name="revision" type="mw:RevisionType" />
+ <element name="upload" type="mw:UploadType" />
+ </choice>
+ <!-- Zero or One sets of discussion threading data -->
+ <element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
+ </sequence>
+ </complexType>
+ <complexType name="RevisionType">
+ <sequence>
+ <element name="id" type="positiveInteger" />
+ <element name="parentid" type="positiveInteger" minOccurs="0" />
+ <element name="timestamp" type="dateTime" />
+ <element name="contributor" type="mw:ContributorType" />
+ <element name="minor" minOccurs="0" maxOccurs="1" />
+ <element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
+ <element name="text" type="mw:TextType" />
+ <element name="sha1" type="string" />
+ <element name="model" type="mw:ContentModelType" />
+ <element name="format" type="mw:ContentFormatType" />
+ </sequence>
+ </complexType>
+ <complexType name="LogItemType">
+ <sequence>
+ <element name="id" type="positiveInteger" />
+ <element name="timestamp" type="dateTime" />
+ <element name="contributor" type="mw:ContributorType" />
+ <element name="comment" type="mw:CommentType" minOccurs="0" />
+ <element name="type" type="string" />
+ <element name="action" type="string" />
+ <element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
+ <element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
+ <element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
+ </sequence>
+ </complexType>
+ <complexType name="CommentType">
+ <simpleContent>
+ <extension base="string">
+ <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+ <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <complexType name="TextType">
+ <simpleContent>
+ <extension base="string">
+ <attribute ref="xml:space" use="optional" default="preserve" />
+ <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+ <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+ <!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
+ <!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
+ <!-- usage ([0-9]+) and with the "ID" type. -->
+ <attribute name="id" type="NMTOKEN" />
+ <attribute name="bytes" use="optional" type="nonNegativeInteger" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <complexType name="LogTextType">
+ <simpleContent>
+ <extension base="string">
+ <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+ <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <complexType name="LogParamsType">
+ <simpleContent>
+ <extension base="string">
+ <attribute ref="xml:space" use="optional" default="preserve" />
+ </extension>
+ </simpleContent>
+ </complexType>
+ <complexType name="ContributorType">
+ <sequence>
+ <element name="username" type="string" minOccurs="0" />
+ <element name="id" type="nonNegativeInteger" minOccurs="0" />
+ <element name="ip" type="string" minOccurs="0" />
+ </sequence>
+ <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+ <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+ </complexType>
+ <complexType name="UploadType">
+ <sequence>
+ <!-- Revision-style data... -->
+ <element name="timestamp" type="dateTime" />
+ <element name="contributor" type="mw:ContributorType" />
+ <element name="comment" type="string" minOccurs="0" />
+ <!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
+ <element name="filename" type="string" />
+ <!-- URI at which this resource can be obtained -->
+ <element name="src" type="anyURI" />
+ <element name="size" type="positiveInteger" />
+ <!-- TODO: add other metadata fields -->
+ </sequence>
+ </complexType>
+ <!-- Discussion threading data for LiquidThreads -->
+ <complexType name="DiscussionThreadingInfo">
+ <sequence>
+ <element name="ThreadSubject" type="string" />
+ <element name="ThreadParent" type="positiveInteger" />
+ <element name="ThreadAncestor" type="positiveInteger" />
+ <element name="ThreadPage" type="string" />
+ <element name="ThreadID" type="positiveInteger" />
+ <element name="ThreadAuthor" type="string" />
+ <element name="ThreadEditStatus" type="string" />
+ <element name="ThreadType" type="string" />
+ </sequence>
+ </complexType>
diff --git a/docs/export-demo.xml b/docs/export-demo.xml
index 591f675c..fd47d13a 100644
--- a/docs/export-demo.xml
+++ b/docs/export-demo.xml
@@ -1,15 +1,18 @@
-<mediawiki xmlns="" xmlns:xsi="" xsi:schemaLocation="" version="0.8" xml:lang="en">
+<mediawiki xmlns="" xmlns:xsi="" xsi:schemaLocation="" version="0.9" xml:lang="en">
<!-- Optional global configuration info -->
<!-- Site name, as set in $wgSitename -->
+ <!-- Database name, as set in $wgDBname -->
+ <dbname>demowiki</dbname>
<!-- Forgot where you got this set? -->
<!-- Source software version -->
- <generator>MediaWiki 1.20</generator>
+ <generator>MediaWiki 1.24</generator>
<!-- Title case sensitivity options of the wiki this data came from -->
<!-- May be 'first-letter', 'case-sensitive', or 'case-insensitive' -->
diff --git a/docs/hooks.txt b/docs/hooks.txt
index 5aaf5961..910d812e 100644
--- a/docs/hooks.txt
+++ b/docs/hooks.txt
@@ -250,6 +250,7 @@ $block: The block from which the autoblock is coming.
'AbortEmailNotification': Can be used to cancel email notifications for an edit.
$editor: The User who made the change.
$title: The Title of the page that was edited.
+$rc: The current RecentChange object.
'AbortLogin': Return false to cancel account login.
$user: the User object being authenticated against
@@ -269,11 +270,19 @@ $reason: the reason for the move (added in 1.13)
'AbortNewAccount': Return false to cancel explicit account creation.
$user: the User object about to be created (read-only, incomplete)
&$msg: out parameter: HTML to display on abort
+&$status: out parameter: Status object to return, replaces the older $msg param (added in 1.23)
+ Create the object with Status::newFatal() to ensure proper API error messages
+ are returned when creating account through API clients.
'AbortTalkPageEmailNotification': Return false to cancel talk page email notification
$targetUser: the user whom to send talk page email notification
$title: the page title
+'SendWatchlistEmailNotification': Return true to send watchlist email notification
+$targetUser: the user whom to send watchlist email notification
+$title: the page title
+$enotif: EmailNotification object
'AbortChangePassword': Return false to cancel password change.
$user: the User object to which the password change is occuring
$mOldpass: the old password provided by the user
@@ -295,18 +304,14 @@ $article: Article object
$user: the User object that was created. (Parameter added in 1.7)
$byEmail: true when account was created "by email" (added in 1.12)
-'AfterFinalPageOutput': At the end of OutputPage::output() but before final
-ob_end_flush() which will send the buffered output to the client. This allows
-for last-minute modification of the output within the buffer by using
-&$output: OutputPage object
+'AddNewAccountApiForm': Allow modifying internal login form when creating an account via API.
+$apiModule: the ApiCreateAccount module calling
+$loginForm: the LoginForm used
-'AfterImportPage': When a page import is completed.
-$title: Title under which the revisions were imported
-$origTitle: Title provided by the XML file
-$revCount: Number of revisions in the XML file
-$sRevCount: Number of successfully imported revisions
-$pageInfo: associative array of page information
+'AddNewAccountApiResult': Modify API output when creating a new account via API.
+$apiModule: the ApiCreateAccount module calling
+$loginForm: the LoginForm used
+&$result: associative array for API result data
'AfterFinalPageOutput': Nearly at the end of OutputPage::output() but
before OutputPage::sendCacheControl() and final ob_end_flush() which
@@ -314,10 +319,19 @@ will send the buffered output to the client. This allows for last-minute
modification of the output within the buffer by using ob_get_clean().
$output: The OutputPage object where output() was called
-'AjaxAddScript': Called in output page just before the initialisation
-of the javascript ajax engine. The hook is only called when ajax
-is enabled ( $wgUseAjax = true; ).
-&$output: OutputPage object
+'AfterImportPage': When a page import is completed.
+$title: Title under which the revisions were imported
+$origTitle: Title provided by the XML file
+$revCount: Number of revisions in the XML file
+$sRevCount: Number of successfully imported revisions
+$pageInfo: associative array of page information
+'AfterParserFetchFileAndTitle': After an image gallery is formed by Parser,
+just before adding its HTML to parser output.
+$parser: Parser object that called the hook
+$ig: Gallery, an object of one of the gallery classes (inheriting from
+$html: HTML generated by the gallery
'AlternateEdit': Before checking if a user can edit a page and before showing
the edit form ( EditPage::edit() ). This is triggered on &action=edit.
@@ -347,6 +361,9 @@ $body: Body of the message
this to extend core API modules.
&$module: Module object
+'ApiBeforeMain': Before calling ApiMain's execute() method in api.php.
+&$main: ApiMain object
'ApiCheckCanExecute': Called during ApiMain::checkCanExecute. Use to further
authenticate and authorize API clients before executing the module. Return
false and set a message to cancel the request.
@@ -376,16 +393,6 @@ descriptions.
&$module: ApiBase Module object
&$desc: Array of parameter descriptions
-'APIGetResultProperties': Use this hook to modify the properties in a module's
-&$module: ApiBase Module object
-&$properties: Array of properties
-'APIGetPossibleErrors': Use this hook to modify the module's list of possible
-$module: ApiBase Module object
-&$possibleErrors: Array of possible errors
'APIQueryAfterExecute': After calling the execute() method of an
action=query submodule. Use this to extend core API modules.
&$module: Module object
@@ -395,36 +402,39 @@ an action=query submodule. Use this to extend core API modules.
&$module: Module object
&$resultPageSet: ApiPageSet object
-'APIQueryInfoTokens': Use this hook to add custom tokens to prop=info. Every
-token has an action, which will be used in the intoken parameter and in the
-output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($pageid, $title), where $pageid is the page ID of the
-page the token is requested for and $title is the associated Title object. In
-the hook, just add your callback to the $tokenFunctions array and return true
-(returning false makes no sense).
+'APIQueryInfoTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to prop=info. Every token has an action,
+which will be used in the intoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title), where $pageid is the page ID of the page the
+token is requested for and $title is the associated Title object. In the hook,
+just add your callback to the $tokenFunctions array and return true (returning
+false makes no sense).
$tokenFunctions: array(action => callback)
-'APIQueryRevisionsTokens': Use this hook to add custom tokens to prop=revisions.
-Every token has an action, which will be used in the rvtoken parameter and in
-the output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($pageid, $title, $rev), where $pageid is the page ID
-of the page associated to the revision the token is requested for, $title the
+'APIQueryRevisionsTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to prop=revisions. Every token has an
+action, which will be used in the rvtoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title, $rev), where $pageid is the page ID of the
+page associated to the revision the token is requested for, $title the
associated Title object and $rev the associated Revision object. In the hook,
just add your callback to the $tokenFunctions array and return true (returning
false makes no sense).
$tokenFunctions: array(action => callback)
-'APIQueryRecentChangesTokens': Use this hook to add custom tokens to
-list=recentchanges. Every token has an action, which will be used in the rctoken
-parameter and in the output (actiontoken="..."), and a callback function which
-should return the token, or false if the user isn't allowed to obtain it. The
-prototype of the callback function is func($pageid, $title, $rc), where $pageid
-is the page ID of the page associated to the revision the token is requested
-for, $title the associated Title object and $rc the associated RecentChange
-object. In the hook, just add your callback to the $tokenFunctions array and
-return true (returning false makes no sense).
+'APIQueryRecentChangesTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to list=recentchanges. Every token has an
+action, which will be used in the rctoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title, $rc), where $pageid is the page ID of the
+page associated to the revision the token is requested for, $title the
+associated Title object and $rc the associated RecentChange object. In the
+hook, just add your callback to the $tokenFunctions array and return true
+(returning false makes no sense).
$tokenFunctions: array(action => callback)
'APIQuerySiteInfoGeneralInfo': Use this hook to add extra information to the
@@ -436,13 +446,19 @@ $module: the current ApiQuerySiteInfo module
sites statistics information.
&$results: array of results, add things here
-'APIQueryUsersTokens': Use this hook to add custom token to list=users. Every
-token has an action, which will be used in the ustoken parameter and in the
-output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($user) where $user is the User object. In the hook,
-just add your callback to the $tokenFunctions array and return true (returning
-false makes no sense).
+'ApiQueryTokensRegisterTypes': Use this hook to add additional token types to
+action=query&meta=tokens. Note that most modules will probably be able to use
+the 'csrf' token instead of creating their own token types.
+&$salts: array( type => salt to pass to User::getEditToken() )
+'APIQueryUsersTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom token to list=users. Every token has an action,
+which will be used in the ustoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($user) where $user is the User object. In the hook, just add
+your callback to the $tokenFunctions array and return true (returning false
+makes no sense).
$tokenFunctions: array(action => callback)
'ApiMain::onException': Called by ApiMain::executeActionWithErrorHandling() when
@@ -456,11 +472,18 @@ key for the array that represents the service data. In this data array, the
key-value-pair identified by the apiLink key is required.
&$apis: array of services
-'ApiTokensGetTokenTypes': Use this hook to extend action=tokens with new token
+'ApiTokensGetTokenTypes': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to extend action=tokens with new token types.
&$tokenTypes: supported token types in format 'type' => callback function
used to retrieve this type of tokens.
+'Article::MissingArticleConditions': Before fetching deletion & move log entries
+to display a message of a non-existing page being deleted/moved, give extensions
+a chance to hide their (unrelated) log entries.
+&$conds: Array of query conditions (all of which have to be met; conditions will
+AND in the final query)
+$logTypes: Array of log types being queried
'ArticleAfterFetchContent': After fetching content of an article from the
database. DEPRECATED, use ArticleAfterFetchContentObject instead.
$article: the article (object) being loaded from the database
@@ -519,6 +542,7 @@ $wikiPage: WikiPage (object) being modified
$title: Title (object) used to create the article object
$article: Article (object) that will be returned
+$context: IContextSource (object)
'ArticleInsertComplete': After a new article is created. DEPRECATED, use
@@ -609,6 +633,7 @@ $title: Title corresponding to the article restored
$create: Whether or not the restoration caused the page to be created (i.e. it
didn't exist before).
$comment: The comment associated with the undeletion.
+$oldPageId: ID of page previously deleted (from archive table)
'ArticleUndeleteLogEntry': When a log entry is generated but not yet saved.
$pageArchive: the PageArchive object
@@ -681,6 +706,12 @@ pages or galleries in category pages.
$name: Image name being checked
&$bad: Whether or not the image is "bad"
+'BaseTemplateAfterPortlet': After output of portlets, allow injecting
+custom HTML after the section. Any uses of the hook need to handle escaping.
+$template BaseTemplate
+$portlet: string portlet name
+&$html: string
'BeforeDisplayNoArticleText': Before displaying message key "noarticletext" or
"noarticletext-nopermission" at Article::showMissingArticle().
$article: article object
@@ -698,6 +729,13 @@ $mediaWiki: Mediawiki object
&$out: OutputPage object
&$skin: Skin object
+'BeforeHttpsRedirect': Prior to forcing HTTP->HTTPS redirect. Gives a chance to
+override how the redirect is output by modifying, or by returning false, and
+letting standard HTTP rendering take place.
+ATTENTION: This hook is likely to be removed soon due to overall design of the system.
+$context: IContextSource object
+&$redirect: string URL, modifiable
'BeforePageRedirect': Prior to sending an HTTP redirect. Gives a chance to
override how the redirect is output by modifying, or by returning false and
taking over the output.
@@ -753,6 +791,7 @@ $block: Block object (which is set to be autoblocking)
'BlockIp': Before an IP address or user is blocked.
$block: the Block object about to be saved
$user: the user _doing_ the block (not the one being blocked)
+&$reason: if the hook is aborted, the error message to be returned in an array
'BlockIpComplete': After an IP address or user is blocked.
$block: the Block object that was saved
@@ -765,7 +804,7 @@ $output: OutputPage object in use
'CanIPUseHTTPS': Determine whether the client at a given source IP is likely
to be able to access the wiki via HTTPS.
$ip: The IP address in human-readable form
-&$canDo: This reference should be set to false if the client may not be able
+&$canDo: This reference should be set to false if the client may not be able
to use HTTPS
'CanonicalNamespaces': For extensions adding their own namespaces or altering
@@ -804,6 +843,34 @@ ChangePassword form via the Preferences form.
$unpatrolled: Whether or not we are showing unpatrolled changes.
$watched: Whether or not the change is watched by the user.
+'ChangesListInitRows': Batch process change list rows prior to rendering.
+$changesList: ChangesList instance
+$rows: The data that will be rendered. May be a ResultWrapper instance or
+ an array.
+'ChangesListSpecialPageFilters': Called after building form options on pages inheriting from ChangesListSpecialPage (in core: RecentChanges, RecentChangesLinked and Watchlist).
+$special: ChangesListSpecialPage instance
+&$filters: associative array of filter definitions. The keys are the HTML
+ name/URL parameters. Each key maps to an associative array with a 'msg'
+ (message key) and a 'default' value.
+'ChangesListSpecialPageQuery': Called when building SQL query on pages inheriting from ChangesListSpecialPage (in core: RecentChanges, RecentChangesLinked and Watchlist).
+$name: name of the special page, e.g. 'Watchlist'
+&$tables: array of tables to be queried
+&$fields: array of columns to select
+&$conds: array of WHERE conditionals for query
+&$query_options: array of options for the database request
+&$join_conds: join conditions for the tables
+$opts: FormOptions for this request
+'LoginUserMigrated': Called during login to allow extensions the opportunity to
+inform a user that their username doesn't exist for a specific reason, instead
+of letting the login form give the generic error message that the account does
+not exist. For example, when the account has been renamed or deleted.
+$user: the User object being authenticated against.
+&$msg: the message identifier for abort reason, or an array to pass a message
+ key and parameters.
'Collation::factory': Called if $wgCategoryCollation is an unknown collation.
$collationName: Name of the collation in question
&$collationObject: Null. Replace with a subclass of the Collation class that
@@ -823,6 +890,28 @@ content model name, but no entry for that model exists in $wgContentHandlers.
$modeName: the requested content model name
&$handler: set this to a ContentHandler object, if desired.
+'ContentModelCanBeUsedOn': Called to determine whether that content model can
+be used on a given page. This is especially useful to prevent some content models
+to be used in some special location.
+$contentModel: ID of the content model in question
+$title: the Title in question.
+&$ok: Output parameter, whether it is OK to use $contentModel on $title.
+Handler functions that modify $ok should generally return false to prevent further
+hooks from further modifying $ok.
+'ContentGetParserOutput': Customize parser output for a given content object,
+called by AbstractContent::getParserOutput. May be used to override the normal
+model-specific rendering of page content.
+$content: The Content to render
+$title: Title of the page, as context
+$revId: The revision ID, as context
+$options: ParserOptions for rendering. To avoid confusing the parser cache,
+the output can only depend on parameters provided to this hook function, not on global state.
+$generateHtml: boolean, indicating whether full HTML should be generated. If false,
+generation of HTML may be skipped, but other information should still be present in the
+ParserOutput object.
+&$output: ParserOutput, to manipulate or replace
'ConvertContent': Called by AbstractContent::convert when a conversion to another
content model is requested.
$content: The Content object to be converted.
@@ -875,8 +964,9 @@ $new: the ?new= param value from the url
'DiffRevisionTools': Override or extend the revision tools available from the
diff view, i.e. undo, etc.
-$rev: Revision object
+$newRev: Revision object of the "new" revision
&$links: Array of HTML links
+$oldRev: Revision object of the "old" revision (may be null)
'DiffViewHeader': Called before diff display
$diff: DifferenceEngine object that's calling
@@ -891,7 +981,7 @@ $oldid: oldid (int) being viewed
'DoEditSectionLink': Override the HTML generated for section edit links
$skin: Skin object rendering the UI
$title: Title object for the title being linked to (may not be the same as
- $wgTitle, if the section is included from a template)
+ the page title, if the section is included from a template)
$section: The designation of the section being pointed to, to be included in
the link, like "&section=$section"
$tooltip: The default tooltip. Escape before using.
@@ -960,6 +1050,12 @@ yourself. Alternatively, modifying $error and returning true will cause the
contents of $error to be echoed at the top of the edit form as wikitext.
Return true without altering $error to allow the edit to proceed.
+'EditPage::showReadOnlyForm:initial': similar to EditPage::showEditForm:initial
+but for the read-only 'view source' variant of the edit form.
+$editor: EditPage instance (object)
+&$out: an OutputPage instance to write to
+return value is ignored (should always return true)
'EditPage::showStandardInputs:options': allows injection of form fields into
the editOptions area
$editor: EditPage instance (object)
@@ -1157,6 +1253,16 @@ $title: Title object that we need to get a sortkey for
underscore) magic words. Called by MagicWord.
&$doubleUnderscoreIDs: array of strings
+'GetExtendedMetadata': Get extended file metadata for the API
+&$combinedMeta: Array of the form: 'MetadataPropName' => array(
+'value' => prop value, 'source' => 'name of hook' ).
+$file: File object of file in question
+$context: RequestContext (including language to use)
+$single: Only extract the current language; if false, the prop value should
+be in the metadata multi-language array format:
+&$maxCacheTime: how long the results can be cached
'GetFullURL': Modify fully-qualified URLs used in redirects/export/offsite data.
$title: Title object of page
$url: string value as output (out parameter, can modify)
@@ -1203,6 +1309,9 @@ without any fancy queries or variants.
$title: Title object of page
&$url: string value as output (out parameter, can modify)
+'GetLogTypesOnUser': Add log types where the target is a userpage
+&$types: Array of log types
'GetMetadataVersion': Modify the image metadata version currently in use. This
is used when requesting image metadata from a ForeignApiRepo. Media handlers
that need to have versioned metadata should add an element to the end of the
@@ -1267,6 +1376,10 @@ page history view, i.e. undo, rollback, etc.
$rev: Revision object
&$links: Array of HTML links
+'HTMLFileCache::useFileCache': Override whether a page should be cached in file
+$context: An IContextSource object with information about the request being served.
'ImageBeforeProduceHTML': Called before producing the HTML created by a wiki
image insertion. You can skip the default logic entirely by returning false, or
just modify a few things using call-by-reference.
@@ -1349,7 +1462,7 @@ $context: IContextSource object
&$pageInfo: Array of information
'InitializeArticleMaybeRedirect': MediaWiki check to see if title is a redirect.
-$title: Title object ($wgTitle)
+$title: Title object for the current page
$request: WebRequest
$ignoreRedirect: boolean to skip redirect check
$target: Title/string of redirect target
@@ -1383,6 +1496,7 @@ $user: user (object) whose email is being invalidated
Callee may modify $url and $query, URL will be constructed as $url . $query
&$url: URL to index.php
&$query: Query string
+$rc: RecentChange object that triggered url generation
'IsFileCacheable': Override the result of Article::isFileCacheable() (if true)
$article: article (object) being checked
@@ -1395,7 +1509,7 @@ $result: Change this value to override the result of wfIsTrustedProxy()
$url: URL used to upload from
&$allowed: Boolean indicating if uploading is allowed for given URL
-'isValidEmailAddr': Override the result of User::isValidEmailAddr(), for
+'isValidEmailAddr': Override the result of Sanitizer::validateEmail(), for
instance to return false if the domain name doesn't match your organization.
$addr: The e-mail address entered by the user
&$result: Set this and return false to override the internal checks
@@ -1440,6 +1554,10 @@ $title: The page's Title.
Currently unused, but planned to provide support for marking individual
language links in the UI, e.g. for featured articles.
+'LanguageSelector': Hook to change the language selector available on a page.
+$out: The output page.
+$cssClassName: CSS class name of the language selector.
'LinkBegin': Used when generating internal and interwiki links in
Linker::link(), before processing starts. Return false to skip default
processing and return $ret. See documentation for Linker::link() for details on
@@ -1483,6 +1601,14 @@ before the return.
&$attribs: the attributes to be applied.
$linkType: The external link type
+'LinkerMakeMediaLinkFile': At the end of Linker::makeMediaLinkFile() just
+before the return.
+$title: the Title object that the link is pointing to
+$file: the File object or false if broken link
+&$html: the link text
+&$attribs: the attributes to be applied
+&$ret: the value to return if your hook returns false
'LinksUpdate': At the beginning of LinksUpdate::doUpdate() just before the
actual update.
&$linksUpdate: the LinksUpdate object
@@ -1523,6 +1649,24 @@ cache.
$cache: The LocalisationCache object
$code: language code
&$alldata: The localisation data from core and extensions
+&purgeBlobs: whether to purge/update the message blobs via MessageBlobStore::clear()
+'LocalisationCacheRecacheFallback': Called for each language when merging
+fallback data into the cache.
+$cache: The LocalisationCache object
+$code: language code
+&$alldata: The localisation data from core and extensions. Note some keys may
+ be omitted if they won't be merged into the final result.
+'LocalisationChecksBlacklist': When fetching the blacklist of
+localisation checks.
+&$blacklist: array of checks to blacklist. See the bottom of
+ maintenance/language/ for the format of this variable.
+'LocalisationIgnoredOptionalMessages': When fetching the list of ignored and
+optional localisation messages
+&$ignored Array of ignored message keys
+&$optional Array of optional message keys
'LogEventsListShowLogExtract': Called before the string is added to OutputPage.
Returning false will prevent the string from being added to the OutputPage.
@@ -1553,6 +1697,11 @@ $password: the password being submitted and found wanting
$retval: a LoginForm class constant with authenticateUserData() return
value (SUCCESS, WRONG_PASS, etc.).
+'LoginPasswordResetMessage': User is being requested to reset their password on login.
+Use this hook to change the Message that will be output on Special:ChangePassword.
+&$msg: Message object that will be shown to the user
+$username: Username of the user who's password was expired.
'LogLine': Processes a single log entry on Special:Log.
$log_type: string for the type of log entry (e.g. 'move'). Corresponds to
logging.log_type database field.
@@ -1567,6 +1716,12 @@ $paramArray: Array of parameters that corresponds to logging.log_params field.
&$revert: string that is displayed in the UI, similar to $comment.
$time: timestamp of the log entry (added in 1.12)
+'LonelyPagesQuery': Allow extensions to modify the query used by
+&$tables: tables to join in the query
+&$conds: conditions for the query
+&$joinConds: join conditions for the query
'MaintenanceRefreshLinksInit': before executing the refreshLinks.php maintenance
$refreshLinks: RefreshLinks object
@@ -1574,8 +1729,8 @@ $refreshLinks: RefreshLinks object
'MagicWordwgVariableIDs': When defining new magic words IDs.
$variableIDs: array of strings
-'MakeGlobalVariablesScript': Called right before Skin::makeVariablesScript is
-executed. Ideally, this hook should only be used to add variables that depend on
+'MakeGlobalVariablesScript': Called at end of OutputPage::getJSVars.
+Ideally, this hook should only be used to add variables that depend on
the current page/request; static configuration should be added through
ResourceLoaderGetConfigVars instead.
&$vars: variable (or multiple variables) to be added into the output of
@@ -1598,8 +1753,8 @@ $wcOnlySysopsCanPatrol: config setting indicating whether the user must be a
something completely different, after the basic globals have been set up, but
before ordinary actions take place.
$output: $wgOut
-$article: $wgArticle
-$title: $wgTitle
+$article: Article on which the action will be performed
+$title: Title on which the action will be performed
$user: $wgUser
$request: $wgRequest
$mediaWiki: The $mediawiki object
@@ -1608,11 +1763,41 @@ $mediaWiki: The $mediawiki object
$title: title of the message (string)
$message: value (string), change it to the message you want to define
+'MessageCache::get': When fetching a message. Can be used to override the key
+for customisations. Given and returned message key must be in special format:
+1) first letter must be in lower case according to the content language.
+2) spaces must be replaced with underscores
+&$key: message key (string)
'MessageCacheReplace': When a message page is changed. Useful for updating
$title: name of the page changed.
$text: new contents of the page.
+'MimeMagicInit': Before processing the list mapping MIME types to media types
+and the list mapping MIME types to file extensions.
+As an extension author, you are encouraged to submit patches to MediaWiki's
+core to add new MIME types to mime.types.
+$mimeMagic: Instance of MimeMagic.
+ Use $mimeMagic->addExtraInfo( $stringOfInfo );
+ for adding new MIME info to the list.
+ Use $mimeMagic->addExtraTypes( $stringOfTypes );
+ for adding new MIME types to the list.
+'MimeMagicImproveFromExtension': Allows MW extensions to further improve the
+MIME type detected by considering the file extension.
+$mimeMagic: Instance of MimeMagic.
+$ext: File extension.
+&$mime: MIME type (in/out).
+'MimeMagicGuessFromContent': Allows MW extensions guess the MIME by content.
+$mimeMagic: Instance of MimeMagic.
+&$head: First 1024 bytes of the file in a string (in - Do not alter!).
+&$tail: More or equal than last 65558 bytes of the file in a string
+ (in - Do not alter!).
+$file: File path.
+&$mime: MIME type (out).
'ModifyExportQuery': Modify the query used by the exporter.
$db: The database object to be queried.
&$tables: Tables in the query.
@@ -1620,13 +1805,6 @@ $db: The database object to be queried.
&$opts: Options for the query.
&$join_conds: Join conditions for the query.
-'MonoBookTemplateToolboxEnd': DEPRECATED. Called by Monobook skin after toolbox
-links have been rendered (useful for adding more). Note: this is only run for
-the Monobook skin. To add items to the toolbox you should use the
-SkinTemplateToolboxEnd hook instead, which works for all "SkinTemplate"-type
-$tools: array of tools
'BaseTemplateToolbox': Called by BaseTemplate when building the $toolbox array
and returning it for the skin to output. You can add items to the toolbox while
still letting the skin make final decisions on skin-specific markup conventions
@@ -1743,7 +1921,7 @@ $isMinor: Whether or not the edit was marked as minor
$isWatch: (No longer used)
$section: (No longer used)
$flags: Flags passed to WikiPage::doEditContent()
-$revision: New Revision of the article
+$revision: New Revision of the article (can be null for edits that change nothing)
$status: Status object about to be returned by doEditContent()
$baseRevId: the rev ID (or false) this edit was based on
@@ -1751,7 +1929,7 @@ $baseRevId: the rev ID (or false) this edit was based on
$article: the article that the history is loading for
$context: RequestContext object
-'PageHistoryLineEnding' : Right before the end <li> is added to a history line.
+'PageHistoryLineEnding': Right before the end <li> is added to a history line.
$row: the revision row for this line
$s: the string representing this parsed line
$classes: array containing the <li> element classes
@@ -1764,7 +1942,8 @@ $queryInfo: the query parameters
'PageRenderingHash': Alter the parser cache option hash key. A parser extension
which depends on user options should install this hook and append its values to
the key.
-$hash: reference to a hash key string which can be modified
+&$confstr: reference to a hash key string which can be modified
+$user: User (object) requesting the page
'ParserAfterParse': Called from Parser::parse() just after the call to
Parser::internalParse() returns.
@@ -1837,7 +2016,7 @@ needs formatting. If nothing handles this hook, the default is to use "$key" to
get the label, and "$key-value" or "$key-value-text"/"$key-value-html" to
format the value.
$key: Key for the limit report item (string)
-$value: Value of the limit report item
+&$value: Value of the limit report item
&$report: String onto which to append the data
$isHTML: If true, $report is an HTML table with two columns; if false, it's
text intended for display in a monospaced font.
@@ -1845,7 +2024,8 @@ $localize: If false, $report should be output in English.
'ParserLimitReportPrepare': Called at the end of Parser:parse() when the parser will
include comments about size of the text parsed. Hooks should use
-$output->setLimitReportData() to populate data.
+$output->setLimitReportData() to populate data. Functions for this hook should
+not use $wgLang; do that in ParserLimitReportFormat instead.
$parser: Parser object
$output: ParserOutput object
@@ -1883,6 +2063,7 @@ that tests continue to run properly.
my talk page, my contributions" etc).
&$personal_urls: Array of link specifiers (see SkinTemplate.php)
&$title: Title object representing the current page
+$skin: SkinTemplate object providing context (e.g. to check if the user is logged in, etc.)
'PingLimiter': Allows extensions to override the results of User::pingLimiter().
&$user : User performing the action
@@ -1899,12 +2080,28 @@ $oldtext : the text of the article before editing
$subject : subject of the new section
&$text : text of the new section
+'PostLoginRedirect': Modify the post login redirect behavior.
+Occurs after signing up or logging in, allows for interception of redirect.
+&$returnTo: The page name to return to, as a string
+&$returnToQuery: array of url parameters, mapping parameter names to values
+&$type: type of login redirect as string;
+ error: display a return to link ignoring $wgRedirectOnLogin
+ signup: display a return to link using $wgRedirectOnLogin if needed
+ success: display a return to link using $wgRedirectOnLogin if needed
+ successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed
'PreferencesGetLegend': Override the text used for the <legend> of a
preferences section.
$form: the PreferencesForm object. This is a ContextSource as well
$key: the section name
&$legend: the legend text. Defaults to wfMessage( "prefs-$key" )->text() but may be overridden
+'PreferencesFormPreSave': Override preferences being saved
+ $formData: array of user submitted data
+ $form: PreferencesForm object, also a ContextSource
+ $user: User object with preferences to be saved set
+ &$result: boolean indicating success
'PrefixSearchBackend': Override the title prefix search used for OpenSearch and
AJAX search suggestions. Put results into &$results outparam and return false.
$ns : array of int namespace keys to search in
@@ -1939,7 +2136,7 @@ $article: the page the form is shown for
$out: OutputPage object
'RawPageViewBeforeOutput': Right before the text is blown out in action=raw.
-&$obj: RawPage object
+&$obj: RawAction object
&$text: The text that's going to be the output
'RecentChange_save': Called at the end of RecentChange::save().
@@ -1957,22 +2154,20 @@ IContextSource $context: The RequestContext the skin is being created for.
&$skin: A variable reference you may set a Skin instance or string key on to
override the skin that will be used for the context.
+'ResetPasswordExpiration': Allow extensions to set a default password expiration
+$user: The user having their password expiration reset
+&$newExpire: The new expiration date
'ResetSessionID': Called from wfResetSessionID
$oldSessionID: old session id
$newSessionID: new session id
'ResourceLoaderGetConfigVars': Called at the end of
-ResourceLoaderStartUpModule::getConfig(). Use this to export static
+ResourceLoaderStartUpModule::getConfigSettings(). Use this to export static
configuration variables to JavaScript. Things that depend on the current page
or request state must be added through MakeGlobalVariablesScript instead.
&$vars: array( variable name => value )
-'ResourceLoaderGetStartupModules': Run once the startup module is being
-generated. This allows you to add modules to the startup module. This hook
-should be used sparingly since any module added here will be loaded on all
-pages. This hook is useful if you want to make code available to module loader
'ResourceLoaderRegisterModules': Right before modules information is required,
such as when responding to a resource
loader request or generating HTML output.
@@ -2022,12 +2217,6 @@ searches.
$term : Search term string
&$title : Current Title object that is being returned (null if none found).
-'SearchEngineReplacePrefixesComplete': Run after SearchEngine::replacePrefixes().
-$searchEngine : The SearchEngine object. Users of this hooks will be interested
-in the $searchEngine->namespaces array.
-$query : Original query.
-&$parsed : Resultant query with the prefixes stripped.
'SearchResultInitFromTitle': Set the revision used when displaying a page in
search results.
$title : Current Title object being displayed in search results.
@@ -2036,13 +2225,21 @@ $title : Current Title object being displayed in search results.
'SearchableNamespaces': An option to modify which namespaces are searchable.
&$arr : Array of namespaces ($nsId => $name) which will be used.
+'SelfLinkBegin': Called before a link to the current article is displayed to
+allow the display of the link to be customized.
+$nt: the Title object
+&$html: html to display for the link
+&$trail: optional text to display before $html
+&$prefix: optional text to display after $html
+&$ret: the value to return if your hook returns false
'SetupAfterCache': Called in Setup.php, after cache objects are set
'ShowMissingArticle': Called when generating the output for a non-existent page.
$article: The article object corresponding to the page
'ShowRawCssJs': Customise the output of raw CSS and JavaScript in page views.
-DEPRECATED, use the ContentHandler facility to handle CSS and JavaScript!
+DEPRECATED, use the ContentGetParserOutput hook instead!
$text: Text being shown
$title: Title of the custom script/stylesheet page
$output: Current OutputPage object
@@ -2097,6 +2294,12 @@ $skin: Skin object
&$bar: Sidebar contents
Modify $bar to add or modify sidebar portlets.
+'SidebarBeforeOutput': Allows to edit sidebar just before its output by skins.
+$skin Skin object
+&$bar: Sidebar content
+Modify $bar to add or modify sidebar portlets.
+Warning: This hook is run on each display. You should consider to use 'SkinBuildSidebar' that is aggressively cached.
'SkinCopyrightFooter': Allow for site and per-namespace customization of
copyright notice.
$title: displayed page title
@@ -2105,12 +2308,18 @@ $type: 'normal' or 'history' for old/diff views
message must be in HTML format, not wikitext!
&$link: overridable HTML link to be passed into the message as $1
&$forContent: overridable flag if copyright footer is shown in content language.
+ This parameter is deprecated.
'SkinGetPoweredBy': TODO
&$text: additional 'powered by' icons in HTML. Note: Modern skin does not use
the MediaWiki icon but plain text instead.
$skin: Skin object
+'SkinPreloadExistence': Supply titles that should be added to link existence
+cache before the page is rendered.
+&$titles: Array of Title objects
+$skin: Skin object
'SkinSubPageSubtitle': At the beginning of Skin::subPageSubtitle().
&$subpages: Subpage links HTML
$skin: Skin object
@@ -2125,6 +2334,14 @@ link" tab.
$sktemplate: SkinTemplate object
$nav_urls: array of tabs
+'SkinTemplateGetLanguageLink': After building the data for a language link from
+which the actual html is constructed.
+&$languageLink: array containing data about the link. The following keys can be
+ modified: href, text, title, class, lang, hreflang. Each of them is a string.
+$languageLinkTitle: Title object belonging to the external language link.
+$title: Title object of the page the link belongs to.
+$outputPage: The OutputPage object the links are built from.
To alter the structured navigation links in SkinTemplates, there are three
hooks called in different spots:
@@ -2173,8 +2390,18 @@ software.
$software: The array of software in format 'name' => 'version'. See
+'SpecialPageBeforeFormDisplay': Before executing the HTMLForm object.
+$name: name of the special page
+&$form: HTMLForm object
+'SpecialBlockModifyFormFields': Add more fields to Special:Block
+$sp: SpecialPage object, for context
+&$fields: Current HTMLForm fields
'SpecialContributionsBeforeMainOutput': Before the form on Special:Contributions
-$id: User identifier
+$id: User id number, only provided for backwards-compatibility
+$user: User object representing user contributions are being fetched for
+$sp: SpecialPage instance, providing context
'SpecialListusersDefaultQuery': Called right before the end of
@@ -2221,7 +2448,7 @@ $special: the special page object
name/URL parameters. Each key maps to an associative array with a 'msg'
(message key) and a 'default' value.
-'SpecialPage_initList': Called when setting up SpecialPage::$mList, use this
+'SpecialPage_initList': Called when setting up SpecialPageFactory::$list, use this
hook to remove a core special page.
$list: list (array) of core special pages
@@ -2251,7 +2478,7 @@ use this to change some selection criteria or substitute a different title.
result from the normal query
'SpecialRecentChangesFilters': Called after building form options at
+RecentChanges. Deprecated, use ChangesListSpecialPageFilters instead.
$special: the special page object
&$filters: associative array of filter definitions. The keys are the HTML
name/URL parameters. Each key maps to an associative array with a 'msg'
@@ -2263,7 +2490,8 @@ SpecialRecentChanges.
$opts: FormOptions for this request
'SpecialRecentChangesQuery': Called when building SQL query for
-SpecialRecentChanges and SpecialRecentChangesLinked.
+SpecialRecentChanges and SpecialRecentChangesLinked. Deprecated, use
+ChangesListSpecialPageQuery instead.
&$conds: array of WHERE conditionals for query
&$tables: array of tables to be queried
&$join_conds: join conditions for the tables
@@ -2281,10 +2509,6 @@ go to the existing page.
$t: title object searched for
&$params: an array of the default message name and page title (as parameter)
-'SpecialSearchGo': Called when user clicked the "Go".
-&$title: title object generated from the text entered by the user
-&$term: the search term entered by the user
'SpecialSearchNogomatch': Called when user clicked the "Go" button but the
target doesn't exist.
&$title: title object generated from the text entered by the user
@@ -2318,24 +2542,11 @@ $specialSearch: SpecialSearch object ($this)
$output: $wgOut
$term: Search term specified by the user
-'SpecialSearchResultsAppend': Called after all search results HTML has
-been output. Note that in some cases, this hook will not be called (no
-results, too many results, SpecialSearchResultsPrepend returned false,
-$specialSearch: SpecialSearch object ($this)
-$output: $wgOut
-$term: Search term specified by the user
-'SpecialSearchResults': Called before search result display when there are
+'SpecialSearchResults': Called before search result display
$term: string of search term
&$titleMatches: empty or SearchResultSet object
&$textMatches: empty or SearchResultSet object
-'SpecialSearchNoResults': Called before search result display when there are no
-$term: string of search term
'SpecialStatsAddExtra': Add extra statistic at the end of Special:Statistics.
&$extraStats: Array to save the new stats
( $extraStats['<name of statistic>'] => <value>; )
@@ -2344,29 +2555,27 @@ $term: string of search term
$form: The SpecialUpload object
-'SpecialVersionExtensionTypes': Called when generating the extensions credits,
-use this to change the tables headers.
-$extTypes: associative array of extensions types
'SpecialVersionVersionUrl': Called when building the URL for Special:Version.
$wgVersion: Current $wgVersion for you to use
&$versionUrl: Raw url to link to (eg: release notes)
'SpecialWatchlistFilters': Called after building form options at Watchlist.
+Deprecated, use ChangesListSpecialPageFilters instead.
$special: the special page object
&$filters: associative array of filter definitions. The keys are the HTML
name/URL parameters. Each key maps to an associative array with a 'msg'
(message key) and a 'default' value.
'SpecialWatchlistQuery': Called when building sql query for SpecialWatchlist.
+Deprecated, use ChangesListSpecialPageQuery instead.
&$conds: array of WHERE conditionals for query
&$tables: array of tables to be queried
&$join_conds: join conditions for the tables
&$fields: array of query fields
-$values: array of variables with watchlist options
+$opts: A FormOptions object with watchlist options for the current request
'SpecialWatchlistGetNonRevisionTypes': Called when building sql query for
-SpecialWatchlist. Allows extensions to register custom values they have
+SpecialWatchlist. Allows extensions to register custom values they have
inserted to rc_type so they can be returned as part of the watchlist.
&$nonRevisionTypes: array of values in the rc_type field of recentchanges table
@@ -2389,6 +2598,10 @@ database result.
&$titleArray: set this to an object to override the default object returned
$res: database result used to create the object
+'TitleExists': Called when determining whether a page exists at a given title.
+$title: The title being tested.
+&$exists: Whether the title exists.
'TitleQuickPermissions': Called from Title::checkQuickPermissions to add to
or override the quick permissions check.
$title: The Title object being accessed
@@ -2447,6 +2660,7 @@ $nt: new title
$user: user who did the move
$pageid: database ID of the page that's been moved
$redirid: database ID of the created redirect
+$reason: reason for the move
'TitleReadWhitelist': Called at the end of read permissions checks, just before
adding the default error message if nothing allows the user to read the page. If
@@ -2456,7 +2670,7 @@ $user: Current user object
&$whitelisted: Boolean value of whether this title is whitelisted
'TitleSquidURLs': Called to determine which URLs to purge from HTTP caches.
-$this: Title object to purge
+$title: Title object to purge
&$urls: An array of URLs to purge from the caches, to be manipulated.
'UndeleteForm::showHistory': Called in UndeleteForm::showHistory, after a
@@ -2485,8 +2699,10 @@ actions).
$action: action name
$article: article "acted on"
-'UnitTestsList': Called when building a list of files with PHPUnit tests.
-&$files: list of files
+'UnitTestsList': Called when building a list of paths containing PHPUnit tests.
+Since 1.24: Paths pointing to a directory will be recursively scanned for
+test case files matching the suffix "Test.php".
+&$paths: list of test cases and directories to search.
'UnwatchArticle': Before a watch is removed from an article.
$user: user watching
@@ -2535,11 +2751,11 @@ string &$error: output: message key for message to show if upload canceled by
returning false. May also be an array, where the first element is the message
key and the remaining elements are used as parameters to the message.
-'UploadVerifyFile': extra file verification, based on mime type, etc. Preferred
+'UploadVerifyFile': extra file verification, based on MIME type, etc. Preferred
in most cases over UploadVerification.
object $upload: an instance of UploadBase, with all info about the upload
-string $mime: The uploaded file's mime type, as detected by MediaWiki. Handlers
- will typically only apply for specific mime types.
+string $mime: The uploaded file's MIME type, as detected by MediaWiki. Handlers
+ will typically only apply for specific MIME types.
object &$error: output: true if the file is valid. Otherwise, an indexed array
representing the problem with the file, where the first element is the message
key and the remaining elements are used as parameters to the message.
@@ -2579,27 +2795,11 @@ $user: User (object) whose permission is being checked
'UserClearNewTalkNotification': Called when clearing the "You have new
messages!" message, return false to not delete it.
$user: User (object) that will clear the message
-'UserComparePasswords': Called when checking passwords, return false to
-override the default password checks.
-&$hash: String of the password hash (from the database)
-&$password: String of the plaintext password the user entered
-&$userId: Integer of the user's ID or Boolean false if the user ID was not
- supplied
-&$result: If the hook returns false, this Boolean value will be checked to
- determine if the password was valid
+$oldid: ID of the talk page revision being viewed (0 means the most recent one)
'UserCreateForm': change to manipulate the login form
$template: SimpleTemplate instance for the form
-'UserCryptPassword': Called when hashing a password, return false to implement
-your own hashing method.
-&$password: String of the plaintext password to encrypt
-&$salt: String of the password salt or Boolean false if no salt is provided
-&$wgPasswordSalt: Boolean of whether the salt is used in the default hashing
- method
-&$hash: If the hook returns false, this String will be used as the hash
'UserEffectiveGroups': Called in User::getEffectiveGroups().
$user: User to get groups for
&$groups: Current effective groups
@@ -2709,6 +2909,15 @@ to be switched to HTTPS.
$user: User in question.
&$https: Boolean whether $user should be switched to HTTPS.
+'UserResetAllOptions': Called in User::resetOptions() when user preferences
+have been requested to be reset. This hook can be used to exclude certain
+options from being reset even when the user has requested all prefs to be reset,
+because certain options might be stored in the user_properties database table
+despite not being visible and editable via Special:Preferences.
+$user: the User (object) whose preferences are being reset
+&$newOptions: array of new (site default) preferences
+$options: array of the user's old preferences
+$resetKinds: array containing the kinds of preferences to reset
'UserRetrieveNewTalks': Called when retrieving "You have new messages!"
@@ -2743,6 +2952,17 @@ $userId: User id of the current user
$userText: User name of the current user
&$items: Array of user tool links as HTML fragments
+'ValidateExtendedMetadataCache': Called to validate the cached metadata in
+FormatMetadata::getExtendedMeta (return false means cache will be
+invalidated and GetExtendedMetadata hook called again).
+$timestamp: The timestamp metadata was generated
+$file: The file the metadata is for
+'UserMailerChangeReturnPath': Called to generate a VERP return address
+when UserMailer sends an email, with a bounce handling extension.
+$to: Array of MailAddress objects for the recipients
+&$returnPath: The return address string
'WantedPages::getQueryInfo': Called in WantedPagesPage::getQueryInfo(), can be
used to alter the SQL query which gets the list of wanted pages.
&$wantedPages: WantedPagesPage object
@@ -2757,12 +2977,18 @@ $page: WikiPage object to be watched
$user: user that watched
$page: WikiPage object watched
+'WatchlistEditorBeforeFormRender': Before building the Special:EditWatchlist
+form, used to manipulate the list of pages or preload data based on that list.
+&$watchlistInfo: array of watchlisted pages in
+ [namespaceId => ['title1' => 1, 'title2' => 1]] format
'WatchlistEditorBuildRemoveLine': when building remove lines in
&$tools: array of extra links
$title: Title object
$redirect: whether the page is a redirect
$skin: Skin object
+&$link: HTML link to title
'WebRequestPathInfoRouter': While building the PathRouter to parse the
@@ -2775,6 +3001,12 @@ Return false to prevent setting of the cookie.
&$expire: Cookie expiration, as for PHP's setcookie()
$options: Options passed to WebResponse::setcookie()
+'WhatLinksHereProps': Allows annotations to be added to WhatLinksHere
+$row: The DB row of the entry.
+$title: The Title of the page where the link comes FROM
+$target: The Title of the page where the link goes TO
+&$props: Array of HTML strings to display after the title.
'WikiExporter::dumpStableQuery': Get the SELECT query for "stable" revisions
dumps. One, and only one hook should set this, and return false.
&$tables: Database tables to use in the SELECT query
@@ -2796,9 +3028,9 @@ run a MediaWiki cli script.
&$options: Associative array of options, may contain the 'php' and 'wrapper'
-'wgQueryPages': Called when initialising $wgQueryPages, use this to add new
-query pages to be updated with maintenance/updateSpecialPages.php.
-$query: $wgQueryPages itself
+'wgQueryPages': Called when initialising list of QueryPage subclasses, use this
+to add new query pages to be updated with maintenance/updateSpecialPages.php.
+$qp: The list of QueryPages
'XmlDumpWriterOpenPage': Called at the end of XmlDumpWriter::openPage, to allow
extra metadata to be added.
@@ -2826,4 +3058,4 @@ data. Can be used to post-process the results.
of values).
More hooks might be available but undocumented, you can execute
-'php maintenance/findHooks.php' to find hidden ones.
+"php maintenance/findHooks.php" to find hidden ones.
diff --git a/docs/kss/Makefile b/docs/kss/Makefile
new file mode 100644
index 00000000..a7b0c471
--- /dev/null
+++ b/docs/kss/Makefile
@@ -0,0 +1,19 @@
+MEDIAWIKI_LOAD_URL ?= http://localhost/w/load.php
+kss: kssnodecheck
+# Generates CSS of mediawiki.ui and mediawiki.ui.button using ResourceLoader, then applies it to the
+# KSS style guide
+ $(eval KSS_RL_TMP := $(shell mktemp /tmp/tmp.XXXXXXXXXX))
+# Keep module names in strict alphabetical order, so CSS loads in the same order as ResourceLoader's addModuleStyles does; this can affect rendering.
+# See OutputPage::makeResourceLoaderLink.
+ @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.legacy.commonPrint|mediawiki.legacy.shared|mediawiki.ui|mediawiki.ui.anchor|mediawiki.ui.button|mediawiki.ui.checkbox|mediawiki.ui.input&only=styles" > $(KSS_RL_TMP)
+ @node_modules/.bin/kss-node ../../resources/src/mediawiki.ui static/ --css $(KSS_RL_TMP) -t styleguide-template
+ @rm $(KSS_RL_TMP)
+kssopen: kss
+ @echo Opening the generated style guide...
+ @command -v xdg-open >/dev/null 2>&1 || { open ${PWD}/static/index.html; exit 0; }
+ @xdg-open ${PWD}/static/index.html
+ @scripts/
diff --git a/docs/kss/README.txt b/docs/kss/README.txt
new file mode 100644
index 00000000..c383af9e
--- /dev/null
+++ b/docs/kss/README.txt
@@ -0,0 +1,19 @@
+The Makefile, package.json, scripts, styleguide-template, and
+mediawiki.ui/ files and directories here and in
+resources/src/mediawiki.ui/ support the automatic generation
+of CSS documentation from the source LESS files using kss for
+To build and open in your web browser, run:
+MEDIAWIKI_LOAD_URL=mediawiki_hostname/w/load.php make kssopen
+For example,
+MEDIAWIKI_LOAD_URL= make kssopen
+If MediaWiki is running on localhost, you can omit MEDIAWIKI_LOAD_URL.
+To rebuild without opening the web browser, run:
+MEDIAWIKI_LOAD_URL=mediawiki_hostname/w/load.php make
diff --git a/docs/kss/package.json b/docs/kss/package.json
new file mode 100644
index 00000000..70cebd2c
--- /dev/null
+++ b/docs/kss/package.json
@@ -0,0 +1,13 @@
+ "name": "mediawiki-ui-dependencies",
+ "description": "Node.js dependencies used for KSS generation",
+ "version": "0.0.1",
+ "dependencies": {
+ "kss": ">=0.3.7"
+ },
+ "repository" : {
+ "type" : "git",
+ "url" : ""
+ }
diff --git a/docs/kss/scripts/ b/docs/kss/scripts/
new file mode 100644
index 00000000..84ee1c4e
--- /dev/null
+++ b/docs/kss/scripts/
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+if command -v npm > /dev/null ; then
+ npm install
+ # If npm isn't installed, but kss-node is, exit normally.
+ # This allows setting it up on one machine, and running it on
+ # another (e.g. Tools Labs execution nodes) that doesn't have npm
+ # installed. However, "npm install" still needs to be run
+ # occasionally to keep kss updated.
+ KSS_NODE="${BASH_SOURCE%/*}/../node_modules/.bin/kss-node"
+ if ! [ -x "$KSS_NODE" ] ; then
+ echo "Neither kss-node nor npm are installed."
+ echo "To install npm, see"
+ echo "When npm is installed, the Makefile can automatically"
+ echo "install kss-node."
+ exit 1
+ fi
diff --git a/docs/kss/styleguide-template/index.html b/docs/kss/styleguide-template/index.html
new file mode 100644
index 00000000..933260ec
--- /dev/null
+++ b/docs/kss/styleguide-template/index.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html class="no-js" lang="en">
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="">
+ <meta name="generator" content="kss-node" />
+ <title>MediaWiki Living Styleguide</title>
+ <link rel="stylesheet" href="public/kss.css">
+ <link rel="stylesheet" href="public/style.css">
+<body><div id="kss-wrapper">
+ <header id="kss-header">
+ <div class="container">
+ <hgroup><h1>Mediawiki.UI</h1></hgroup>
+ </div>
+ </header>
+ <div class="container">
+ <nav>
+ <ul>
+ <li><a href="index.html"><span>0.0</span> Overview</a></li>
+ {{#eachRoot}}
+ <li>
+ <a href="section-{{ reference }}.html">
+ <span>{{ reference }}.0</span> {{ header }}
+ </a>
+ <ul>
+ {{#eachSection reference}}
+ {{#whenDepth 2}}
+ <li>
+ <a href="section-{{../../reference}}.html#section-{{ reference }}">
+ <span>{{ reference }}</span>
+ {{ header }}
+ </a>
+ </li>
+ {{/whenDepth}}
+ {{/eachSection}}
+ </ul>
+ </li>
+ {{/eachRoot}}
+ </ul>
+ </nav>
+ <div class="content">
+ {{#if overview}}
+ {{html overview}}
+ {{else}}
+ {{#eachSection rootNumber}}
+ <div>
+ {{#whenDepth 1}}
+ <h1>{{ reference }}.0 {{ header }}</h1>
+ {{else}}
+ {{#whenDepth 2}}
+ <a name="section-{{ reference }}"></a>
+ <h2>{{ reference }} {{ header }}</h2>
+ {{/whenDepth}}
+ {{#whenDepth 3}}
+ <h3>{{ reference }} {{ header }}</h3>
+ {{/whenDepth}}
+ {{/whenDepth}}
+ {{#ifAny markup modifiers}}
+ <div>{{html description}}</div>
+ <div class="example">
+ <pre class="prettyprint lang-html">{{markup}}</pre>
+ <blockquote>{{modifierMarkup}}</blockquote>
+ </div>
+ {{#eachModifier}}
+ <h4>{{name}}</h4>
+ {{html description}}
+ <blockquote>{{modifierMarkup}}</blockquote>
+ {{/eachModifier}}
+ {{else}}
+ {{#if description}}
+ {{html description}}
+ {{/if}}
+ {{/ifAny}}
+ </div>
+ {{/eachSection}}
+ {{/if}}
+ </div>
+ </div>
diff --git a/docs/kss/styleguide-template/public/kss.less b/docs/kss/styleguide-template/public/kss.less
new file mode 100644
index 00000000..eeea1a87
--- /dev/null
+++ b/docs/kss/styleguide-template/public/kss.less
@@ -0,0 +1,188 @@
+.container {
+ width: 100%;
+nav {
+ display: none;
+.content {
+ .example {
+ blockquote {
+ margin-top: 20px;
+ }
+ }
+body {
+ margin: 0;
+ padding: 0;
+ padding-top: 3px;
+ padding-bottom: 40px;
+ // FIXME: Remove when typography module in mediawiki-ui
+ font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
+.kss-no-margin {
+ // FIXME: Is this being used anywhere? Remove if not.
+ margin: 0;
+.container {
+ margin: 0 auto;
+ display: -webkit-flex;
+ display: flex;
+header {
+ padding: 0;
+ margin: 0;
+ border-bottom: 1px solid #eee;
+ hgroup {
+ min-width: 149px;
+ h1 {
+ padding: 16px 28px;
+ font-size: 15px;
+ text-transform: uppercase;
+ margin: 0;
+ width: 92px;
+ border-right: 1px solid #eee;
+ }
+ }
+nav {
+ -webkit-flex: initial;
+ flex: initial;
+ min-width: 139px;
+ margin-top: 25px;
+ ul {
+ list-style: none;
+ padding: 0;
+ li {
+ margin-left: 10px;
+ margin-bottom: 20px;
+ a {
+ text-transform: uppercase;
+ color: #aaa;
+ font-size: 12px;
+ font-weight: bold;
+ text-decoration: none;
+ &:hover {
+ color: #538DF8;
+ }
+ span {
+ display: inline-block;
+ width: 35px;
+ }
+ }
+ ul {
+ li {
+ margin: 0;
+ }
+ li a {
+ text-transform: none;
+ font-weight: normal;
+ }
+ }
+ }
+ }
+.content {
+ -webkit-flex: 1;
+ flex: 1;
+ h1, h2, h3, h4, h5, h6, p {
+ margin-left: 20px;
+ }
+ p {
+ width: 338px;
+ }
+ h1 {
+ margin-bottom: 0;
+ }
+ .example {
+ display: -webkit-flex;
+ display: flex;
+ flex-wrap: wrap;
+ pre {
+ -webkit-flex: initial;
+ flex: initial;
+ background: #f8f8f8;
+ padding: 20px;
+ color: #999;
+ word-wrap: break-word;
+ // word-wrap in pre not affecting Firefox, so add white-space.
+ white-space: pre-wrap;
+ float: left;
+ margin: 0;
+ margin-right: 22px;
+ }
+ blockquote {
+ -webkit-flex: 1;
+ flex: 1;
+ display: block;
+ margin: 0;
+ margin-left: 20px;
+ div {
+ margin-bottom: 5px;
+ }
+ }
+ }
+@media (min-width: 768px) {
+ nav {
+ display: block;
+ width: 100px;
+ }
+ @columnWidth: (768px - 100px ) / 2;
+ .example {
+ pre,
+ blockquote {
+ width: @columnWidth;
+ }
+ }
+@media (min-width: 980px) {
+ nav {
+ width: auto;
+ }
+ .content {
+ margin-left: 30px;
+ }
+ .container {
+ width: 980px;
+ }
+ .example {
+ pre {
+ width: 338px;
+ }
+ blockquote {
+ width: auto;
+ }
+ }
diff --git a/docs/kss/styleguide-template/public/less.js b/docs/kss/styleguide-template/public/less.js
new file mode 100644
index 00000000..89b76377
--- /dev/null
+++ b/docs/kss/styleguide-template/public/less.js
@@ -0,0 +1,9 @@
+// LESS - Leaner CSS v1.2.1
+// Copyright (c) 2009-2011, Alexis Sellier
+// Licensed under the Apache 2.0 License.
+(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b<a.length;b++)a[b].type.match(k)&&(new d.Parser).parse(a[b].innerHTML||"",function(c,d){var e=d.toCSS(),f=a[b];f.type="text/css",f.styleSheet?f.styleSheet.cssText=e:f.innerHTML=e})}function n(a,b){for(var c=0;c<d.sheets.length;c++)o(d.sheets[c],a,b,d.sheets.length-(c+1))}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//",g.lastIndexOf("/")+1)+i);var m=i.match(/([^\/]+)$/)[1];s(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())r(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type,filename:m})).parse(a,function(d,e){if(d)return w(d,i);try{c(d,e,a,b,{local:!1,lastModified:g,remaining:f}),u(document.getElementById("less-error-message:"+q(i)))}catch(d){w(d,i)}})}catch(h){w(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function q(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function r(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||q(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",||"screen",,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),"GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='<li><label>{line}</label><pre class="{class}">{content}</pre></li>',f=document.createElement("div"),g,h,i=[],j=a.filename||b;,f.className="less-error-message",h="<h3>"+(a.message||"There is an error in your .less file")+"</h3>"+'<p>in <a href="'+j+'">'+j+"</a> ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="<br/>"+a.stack.split("\n").slice(1).join("<br/>"):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":</p>"+"<ul>"+i.join("")+"</ul>"),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return"[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d<c;d++)d in this&&,this[d],d,this)}),||({var b=this.length>>>0,c=new Array(b),d=arguments[1];for(var e=0;e<b;e++)e in this&&(c[e],this[e],e,this));return c}),Array.prototype.filter||(Array.prototype.filter=function(a){var b=[],c=arguments[1];for(var d=0;d<this.length;d++),this[d])&&b.push(this[d]);return b}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=this.length>>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c<b;c++)c in this&&(,d,this[c],c,this));return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=arguments[1]||0;if(!b)return-1;if(c>=b)return-1;c<0&&(c+=b);for(;c<b;c++){if(!,c))continue;if(a===this[c])return c}return-1}),Object.keys||(Object.keys=function(a){var b=[];for(var c in a),c)&&b.push(c);return b}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s\s*/,"").replace(/\s\s*$/,"")});var d,f;typeof environment=="object"&&{}"[object Environment]"?(typeof a=="undefined"?d={}:d=a.less={},f=d.tree={},d.mode="rhino"):typeof a=="undefined"?(d=exports,f=c("./tree"),d.mode="node"):(typeof a.less=="undefined"&&(a.less={}),d=a.less,f=a.less.tree={},d.mode="browser"),d.Parser=function(b){function t(){j=m[i],k=h,n=h}function u(){m[i]=j,h=k,n=h}function v(){h>n&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return;if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h<j){e=g.charCodeAt(h);if(e!==32&&e!==10&&e!==9)break;h++}return m[i]=m[i].slice(d+(h-l)),n=h,m[i].length===0&&i<m.length-1&&i++,typeof b=="string"?b:b.length===1?b[0]:b}}function x(a,b){var c=w(a);if(!!c)return c;y(b||(typeof a=="string"?"expected '"+a+"' got '"+g.charAt(h)+"'":"unexpected token"))}function y(a,b){throw{index:h,type:b||"Syntax",message:a}}function z(a){return typeof a=="string"?g.charAt(h)===a:a.test(m[i])?!0:!1}function A(a,b){return a.filename&&b.filename&&a.filename!==b.filename?o.imports.contents[a.filename]:g}function B(a,b){for(var c=a,d=-1;c>=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,,c)+1,this.callExtract=g[B(,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l<g.length;l++){d.lastIndex=l,(h=d.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0])),m=g.charAt(l),e.lastIndex=l,!k&&!j&&m==="/"&&(n=g.charAt(l+1),(n==="/"||n==="*")&&(h=e.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0]),m=g.charAt(l)));if(m==="{"&&!k&&!j)f++,i.push(m);else if(m==="}"&&!k&&!j)f--,i.push(m),a[++c]=i=[];else if(m==="("&&!k&&!j)i.push(m),j=!0;else if(m===")"&&!k&&j)i.push(m),j=!1;else{if(m==='"'||m==="'"||m==="`")k?k=k===m?!1:k:k=m;i.push(m)}}if(f>0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return{return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h<g.length-1){h=l,t=g.split("\n"),s=(g.slice(0,h).match(/\n/g)||"").length+1;for(var z=h,A=-1;z>=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",^,\s*[^)]+/);if( a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({,value:i})):b.push({}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w({a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(,e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w( b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(;return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var,1),d=b.value;for(var e=0;e<c.length;e++)d=d.replace(/%[sda]/i,function(a){var b=a.match(/s/i)?c[e].value:c[e].toCSS();return a.match(/[A-Z]$/)?encodeURIComponent(b):b});return d=d.replace(/%%/g,"%"),new a.Quoted('"'+d+'"',d)},round:function(a){return this._math("round",a)},ceil:function(a){return this._math("ceil",a)},floor:function(a){return this._math("floor",a)},_math:function(b,d){if(d instanceof a.Dimension)return new a.Dimension(Math[b](c(d)),d.unit);if(typeof d=="number")return Math[b](d);throw{type:"Argument",message:"argument must be a number"}},argb:function(b){return new a.Anonymous(b.toARGB())},percentage:function(b){return new a.Dimension(b.value*100,"%")},color:function(b){if(b instanceof a.Quoted)return new a.Color(b.value.slice(1));throw{type:"Argument",message:"argument must be a string"}},iscolor:function(b){return this._isa(b,a.Color)},isnumber:function(b){return this._isa(b,a.Dimension)},isstring:function(b){return this._isa(b,a.Quoted)},iskeyword:function(b){return this._isa(b,a.Keyword)},isurl:function(b){return this._isa(b,a.URL)},ispixel:function(b){return b instanceof a.Dimension&&b.unit==="px"?a.True:a.False},ispercentage:function(b){return b instanceof a.Dimension&&b.unit==="%"?a.True:a.False},isem:function(b){return b instanceof a.Dimension&&b.unit==="em"?a.True:a.False},_isa:function(b,c){return b instanceof c?a.True:a.False}}})(c("./tree")),function(a){a.colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}}(c("./tree")),function(a){a.Alpha=function(a){this.value=a},a.Alpha.prototype={toCSS:function(){return"alpha(opacity="+(this.value.toCSS?this.value.toCSS():this.value)+")"},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Anonymous=function(a){this.value=a.value||a},a.Anonymous.prototype={toCSS:function(){return this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Assignment=function(a,b){this.key=a,this.value=b},a.Assignment.prototype={toCSS:function(){return this.key+"="+(this.value.toCSS?this.value.toCSS():this.value)},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Call=function(a,b,c,d){,this.args=b,this.index=c,this.filename=d},a.Call.prototype={eval:function(b){var{return a.eval(b)});if(!( in a.functions))return new a.Anonymous("("{return a.toCSS()}).join(", ")+")");try{return a.functions[].apply(a.functions,c)}catch(d){throw{type:d.type||"Runtime",message:"error evaluating function `""`"+(d.message?": "+d.message:""),index:this.index,filename:this.filename}}},toCSS:function(a){return this.eval(a).toCSS()}}}(c("../tree")),function(a){a.Color=function(a,b){Array.isArray(a)?this.rgb=a:a.length==6?this.rgb=a.match(/.{2}/g).map(function(a){return parseInt(a,16)}):this.rgb=a.split("").map(function(a){return parseInt(a+a,16)}),this.alpha=typeof b=="number"?b:1},a.Color.prototype={eval:function(){return this},toCSS:function(){return this.alpha<1?"rgba("{return Math.round(a)}).concat(this.alpha).join(", ")+")":"#"{return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b<c?6:0);break;case b:g=(c-a)/j+2;break;case c:g=(a-b)/j+4}g/=6}return{h:g*360,s:h,l:i,a:d}},toARGB:function(){var a=[Math.round(this.alpha*255)].concat(this.rgb);return"#"{return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(;else{if(!{type:"Type",message:"Unable to perform comparison",index:d};}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value<this.value?1:0:-1}}}(c("../tree")),function(a){a.Directive=function(b,c,d){,this.features=d&&new a.Value(d),Array.isArray(c)?(this.ruleset=new a.Ruleset([],c),this.ruleset.allowImports=!0):this.value=c},a.Directive.prototype={toCSS:function(a,b){var c=this.features?" "+this.features.toCSS(b):"";return this.ruleset?(this.ruleset.root=!0,"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n"))" "+this.value.toCSS()+";\n"},eval:function(a){return this.features=this.features&&this.features.eval(a),a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),typeof c=="string"?this.value=c.trim():c?this.value=c:this.value="",this.index=d},a.Element.prototype.eval=function(b){return new a.Element(this.combinator,this.value.eval?this.value.eval(b):this.value,this.index)},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+(this.value.toCSS?this.value.toCSS(a):this.value)},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression({return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return{return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e<c.rules.length;e++)c.rules[e]instanceof a.Import&&Array.prototype.splice.apply(c.rules,[e,1].concat(c.rules[e].eval(b)));return this.features?new a.Directive("@media",c.rules,this.features.value):c.rules}}}(c("../tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify((new a.Variable("@"+e,d.index)).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: `"+
+f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{}catch(g){throw{message:"JavaScript evaluation error: '"": "+g.message+"'",index:this.index}}return typeof c=="string"?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(c("../tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(b){return b instanceof a.Keyword?b.value===this.value?0:1:-1}},a.True=new a.Keyword("true"),a.False=new a.Keyword("false")}(c("../tree")),function(a){a.mixin={},a.mixin.Call=function(b,c,d,e,f){this.selector=new a.Selector(b),this.arguments=c,this.index=d,this.filename=e,this.important=f},a.mixin.Call.prototype={eval:function(a){var b,c,d=[],e=!1;for(var f=0;f<a.frames.length;f++)if((b=a.frames[f].find(this.selector)).length>0){c=this.arguments&&{return b.eval(a)});for(var g=0;g<b.length;g++)if(b[g].match(c,a))try{Array.prototype.push.apply(d,b[g].eval(a,this.arguments,this.important).rules),e=!0}catch(h){throw{message:h.message,index:h.index,filename:this.filename,stack:h.stack,call:this.index}}if(e)return d;throw{type:"Runtime",message:"No matching definition was found for `"+this.selector.toCSS().trim()+"("{return a.toCSS()}).join(", ")+")`",index:this.index,filename:this.filename}}throw{type:"Name",message:this.selector.toCSS().trim()+" is undefined",index:this.index,filename:this.filename}}},a.mixin.Definition=function(b,c,d,e){,this.selectors=[new a.Selector([new a.Element(null,b)])],this.params=c,this.condition=e,this.arity=c.length,this.rules=d,this._lookups={},this.required=c.reduce(function(a,b){return!||!b.value?a+1:a},0),this.parent=a.Ruleset.prototype,this.frames=[]},a.mixin.Definition.prototype={toCSS:function(){return""},variable:function(a){return,a)},variables:function(){return},find:function(){return this.parent.find.apply(this,arguments)},rulesets:function(){return this.parent.rulesets.apply(this)},evalParams:function(b,c){var d=new a.Ruleset(null,[]);for(var e=0,f;e<this.params.length;e++)if(this.params[e].name){if(!(f=c&&c[e]||this.params[e].value))throw{type:"Runtime",message:"wrong number of arguments for "" ("+c.length+" for "+this.arity+")"};d.rules.unshift(new a.Rule(this.params[e].name,f.eval(b)))}return d},eval:function(b,c,d){var e=this.evalParams(b,c),f,g=[],h;for(var i=0;i<Math.max(this.params.length,c&&c.length);i++)g.push(c[i]||this.params[i].value);return e.rules.unshift(new a.Rule("@arguments",(new a.Expression(g)).eval(b))),h=d?{return new a.Rule(,b.value,"!important",b.index)}):this.rules.slice(0),(new a.Ruleset(null,h)).eval({frames:[this,e].concat(this.frames,b.frames)})},match:function(a,b){var c=a&&a.length||0,d,e;if(c<this.required)return!1;if(this.required>0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;f<d;f++)if(!this.params[f].name&&a[f].eval(b).toCSS()!=this.params[f].value.eval(b).toCSS())return!1;return!0}}}(c("../tree")),function(a){a.Operation=function(a,b){this.op=a.trim(),this.operands=b},a.Operation.prototype.eval=function(b){var c=this.operands[0].eval(b),d=this.operands[1].eval(b),e;if(c instanceof a.Dimension&&d instanceof a.Color){if(this.op!=="*"&&this.op!=="+")throw{name:"OperationError",message:"Can't substract or divide a color from a number"};e=d,d=c,c=e}return c.operate(this.op,d)},a.operate=function(a,b,c){switch(a){case"+":return b+c;case"-":return b-c;case"*":return b*c;case"/":return b/c}}}(c("../tree")),function(a){a.Paren=function(a){this.value=a},a.Paren.prototype={toCSS:function(a){return"("+this.value.toCSS(a)+")"},eval:function(b){return new a.Paren(this.value.eval(b))}}}(c("../tree")),function(a){a.Quoted=function(a,b,c,d){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d},a.Quoted.prototype={toCSS:function(){return this.escaped?this.value:this.quote+this.value+this.quote},eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return(new a.JavaScript(e,c.index,!0)).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=(new a.Variable("@"+e,c.index)).eval(b);return"value"in f?f.value:f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index)}}}(c("../tree")),function(a){a.Rule=function(b,c,d,e,f){,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.index=e,this.inline=f||!1,b.charAt(0)==="@"?this.variable=!0:this.variable=!1},a.Rule.prototype.toCSS=function(a){return this.variable?""":":": ")+this.value.toCSS(a)+this.important+(this.inline?"":";")},a.Rule.prototype.eval=function(b){return new a.Rule(,this.value.eval(b),this.important,this.index,this.inline)},a.Shorthand=function(a,b){this.a=a,this.b=b},a.Shorthand.prototype={toCSS:function(a){return this.a.toCSS(a)+"/"+this.b.toCSS(a)},eval:function(){return this}}}(c("../tree")),function(a){a.Ruleset=function(a,b){this.selectors=a,this.rules=b,this._lookups={}},a.Ruleset.prototype={eval:function(b){var c=this.selectors&&{return a.eval(b)}),d=new a.Ruleset(c,this.rules.slice(0));d.root=this.root,d.allowImports=this.allowImports,b.frames.unshift(d);if(d.root||d.allowImports)for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.Import&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Definition&&(d.rules[e].frames=b.frames.slice(0));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Call&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0,f;e<d.rules.length;e++)f=d.rules[e],f instanceof a.mixin.Definition||(d.rules[e]=f.eval?f.eval(b):f);return b.frames.shift(),d},match:function(a){return!a||a.length===0},variables:function(){return this._variables?this._variables:this._variables=this.rules.reduce(function(b,c){return c instanceof a.Rule&&c.variable===!0&&(b[]=c),b},{})},variable:function(a){return this.variables()[a]},rulesets:function(){return this._rulesets?this._rulesets:this._rulesets=this.rules.filter(function(b){return b instanceof a.Ruleset||b instanceof a.mixin.Definition})},find:function(b,c){c=c||this;var d=[],e,f,g=b.toCSS();return g in this._lookups?this._lookups[g]:(this.rulesets().forEach(function(e){if(e!==c)for(var g=0;g<e.selectors.length;g++)if(f=b.match(e.selectors[g])){b.elements.length>e.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?{return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j<this.rules.length;j++)i=this.rules[j],i.rules||i instanceof a.Directive?f.push(i.toCSS(g,c)):i instanceof a.Comment?i.silent||(this.root?f.push(i.toCSS(c)):e.push(i.toCSS(c))):i.toCSS&&!i.variable?e.push(i.toCSS(c)):i.value&&!i.variable&&e.push(i.value.toString());return f=f.join(""),this.root?d.push(e.join(c.compress?"":"\n")):e.length>0&&({return{return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d<c.length;d++)this.joinSelector(a,b,c[d])},joinSelector:function(b,c,d){var e=[],f=[],g=[],h=[],i=!1,j;for(var k=0;k<d.elements.length;k++)j=d.elements[k],j.combinator.value.charAt(0)==="&"&&(i=!0),i?h.push(j):g.push(j);i||(h=g,g=[]),g.length>0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l<c.length;l++)b.push(e.concat(c[l]).concat(f))}}}(c("../tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){var b=this.elements.length,c=a.elements.length,d=Math.min(b,c);if(b<c)return!1;for(var e=0;e<d;e++)if(this.elements[e].value!==a.elements[e].value)return!1;return!0},a.Selector.prototype.eval=function(b){return new a.Selector({return a.eval(b)}))},a.Selector.prototype.toCSS=function(a){return this._css?{return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("../tree")),function(b){b.URL=function(b,c){ a!="undefined"&&!/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(b.value)&&c.length>0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,"value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value({return a.eval(b)}))},toCSS:function(a){return{return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c<a.length;c++)if(,a[c]))return d;return null},a.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["{return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname==""||location.hostname==""||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),{return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&,d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l<j.length;l++)(j[l].rel==="stylesheet/less"||j[l].rel.match(/stylesheet/)&&j[l].type.match(k))&&d.sheets.push(j[l]);d.refresh=function(a){var b,c;b=c=new Date,n(function(a,d,e,f,g){g.local?v("loading "+f.href+" from cache."):(v("parsed "+f.href+" successfully."),r(d.toCSS(),f,g.lastModified)),v("css for "+f.href+" generated in "+(new Date-c)+"ms"),g.remaining===0&&v("css generated in "+(new Date-b)+"ms"),c=new Date},a),m()},d.refreshStyles=m,d.refresh(d.env==="development")})(window); \ No newline at end of file
diff --git a/docs/language.txt b/docs/language.txt
index 42a60279..8f4cf751 100644
--- a/docs/language.txt
+++ b/docs/language.txt
@@ -2,4 +2,4 @@ language.txt
The Language object handles all readable text produced by the software.
diff --git a/docs/magicword.txt b/docs/magicword.txt
index 1d9bf7d4..6b4d37ee 100644
--- a/docs/magicword.txt
+++ b/docs/magicword.txt
@@ -86,10 +86,10 @@ function wfGetCustomMagicWordValue( &$parser, $var1, $var2 ){
return "custom: var1 is $var1, var2 is $var2";
-Note: the 'ParserFirstCallInit' hook is only aviable since 1.12. To work with
+Note: the 'ParserFirstCallInit' hook is only available since 1.12. To work with
an older version, you'll need to use an extension function.
Online documentation (contains more informations):
-Magic words:
-Parser functions: \ No newline at end of file
+Magic words:
+Parser functions:
diff --git a/docs/maintenance.txt b/docs/maintenance.txt
index 87a32a80..87071f2a 100644
--- a/docs/maintenance.txt
+++ b/docs/maintenance.txt
@@ -54,4 +54,4 @@ require_once RUN_MAINTENANCE_IF_MAIN;
That's it. In the execute() method, you have access to all of the normal
MediaWiki functions, so you can get a DB connection, use the cache, etc.
For full docs on the Maintenance class, see the auto-generated docs at
diff --git a/docs/memcached.txt b/docs/memcached.txt
index a2b4a949..16c57602 100644
--- a/docs/memcached.txt
+++ b/docs/memcached.txt
@@ -78,7 +78,7 @@ usage evenly), make its entry a subarray:
== PHP client for memcached ==
MediaWiki uses a fork of Ryan T. Dean's pure-PHP memcached client.
-The newer PECL module is supported.
+It also supports the PECL PHP extension for memcached.
MediaWiki uses three object for object caching:
* $wgMemc, controlled by $wgMainCacheType
@@ -91,7 +91,7 @@ database. If the cache daemon can't be contacted, it should also
disable itself fairly smoothly.
By default, $wgMemc is used but when it is $parserMemc or $messageMemc
-this is mentionned below.
+this is mentioned below.
== Keys used ==
diff --git a/docs/schema.txt b/docs/schema.txt
index 365576cc..7a92d0a6 100644
--- a/docs/schema.txt
+++ b/docs/schema.txt
@@ -6,4 +6,4 @@ That file has been commented with details of the usage for
each table and field.
Historical information and some other notes are available at
diff --git a/docs/scripts.txt b/docs/scripts.txt
index 0b8ee8f6..c6fa674c 100644
--- a/docs/scripts.txt
+++ b/docs/scripts.txt
@@ -9,16 +9,16 @@ Primary scripts:
Main access point. It handles the most of requests.
- See
+ See
Script to provide an API for bots to fetch content and informations about
- the site and also modify it. See
+ the site and also modify it. See
for more informations.
Script that only serve images to logged in users. To configure the wiki
- to use that script, see
+ to use that script, see
Used by ResourceLoader to serve minified, concatenated and gzipped CSS and JS.
@@ -40,7 +40,7 @@ Primary scripts:
To enable the profileinfo.php itself, you'll need to set $wgDBadminuser
and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo
- See also
+ See also .
Script used to resize images if it is configured to be done when the web
diff --git a/docs/skin.txt b/docs/skin.txt
index 1459d7af..58f77cf8 100644
--- a/docs/skin.txt
+++ b/docs/skin.txt
@@ -55,7 +55,7 @@ These can also be customised on a per-user basis, by editing
This feature has led to a wide variety of "user styles" becoming available:
If you want a different look for your wiki, that gallery is a good place to start.
@@ -76,7 +76,7 @@ This technique is used by the more ambitious MediaWiki site operators, to
create complex custom skins for their wikis. It should be preferred over
editing the core Monobook skin directly.
-See for more information.
+See for more information.
== Extension skins ==
diff --git a/docs/uidesign/confirmable.html b/docs/uidesign/confirmable.html
new file mode 100644
index 00000000..d0358214
--- /dev/null
+++ b/docs/uidesign/confirmable.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+ <meta charset="utf-8">
+ <!--
+ The jquery.confirmable module uses some additional modules and files
+ for internationalization support. These are omitted here for simplicity.
+ -->
+ <script type="text/javascript" src="../../resources/lib/jquery/jquery.js"></script>
+ <link rel="stylesheet" href="../../resources/src/jquery/jquery.confirmable.css">
+ <script type="text/javascript" src="../../resources/src/jquery/jquery.confirmable.js"></script>
+ <style>
+ body {
+ font: small sans-serif;
+ }
+ .mw-rollback-link a,
+ .mw-unwatch-link a,
+ .mw-thanks-thank-link a {
+ background: #ccf;
+ }
+ </style>
+ <h2>Introduction</h2>
+ <p>The jquery.confirmable module provides a simple inline confirmation script for potentially destructive or uncancellable actions.</p>
+ <p>Possible uses include confirmable "rollback" links in histories, confirmable "unwatch" links on watchlists, or confirmable "thanks" links (provided by the Echo extension).</p>
+ <p>Shown below is a demo of how each of those could work on history and watchlist entries, in an LTR and RTL language. The enhanced links are highlighted in blue.</p>
+ <h2>Examples</h2>
+ <h3>LTR (English)</h3>
+ <p>Watchlist:</p>
+ <ul lang="en" dir="ltr">
+ <li class="mw-line-even mw-changeslist-line-not-watched">
+ (<a href="#">diff</a> | <a href="#">hist</a>)
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="mw-title"><a href="#" class="mw-changeslist-title">Example page</a></span>; <span class="mw-changeslist-date">13:38</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="mw-plusminus-neg">(-130)</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <a href="#" class="mw-userlink">Example user</a>
+ <span class="mw-usertoollinks">(<a href="#">Talk</a> | <a href="#">contribs</a> | <a href="#">block</a>)</span>
+ <span class="comment">(example edit)</span>
+ <span class="mw-rollback-link">[<a href="">rollback</a>]</span>
+ (<span class="mw-unwatch-link"><a href="#">unwatch</a></span>)
+ </li>
+ </ul>
+ <p>History:</p>
+ <ul lang="en" dir="ltr">
+ <li>
+ <span class="mw-history-histlinks">(cur | <a href="#">prev</a>)</span>
+ <input type="radio" style="visibility: hidden;" /><input type="radio" checked />
+ <a href="#" class="mw-changeslist-date">13:38, 28 October 2013</a>
+ <span class='history-user'>
+ <a href="#" class="mw-userlink">Example user</a>
+ <span class="mw-usertoollinks">(<a href="#">Talk</a> | <a href="#">contribs</a> | <a href="#">block</a>)</span>
+ </span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="history-size">(1,654 bytes)</span>
+ <span class="mw-plusminus-neg">(-130)</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="comment">(example edit)</span>
+ (<span class="mw-rollback-link"><a href="">rollback 1 edit</a></span> | <span class="mw-history-undo"><a href="#">undo</a></span> | <span class="mw-thanks-thank-link"><a href="#">thank</a></span>)
+ </li>
+ </ul>
+ <script type="text/javascript">
+ $( 'ul[lang="en"] .mw-rollback-link a' )
+ .confirmable({ i18n: { confirm: 'Are you sure you want to rollback?' } });
+ $( 'ul[lang="en"] .mw-unwatch-link a' )
+ .confirmable({ handler: function(){ alert('Unwatched!') } });
+ $( 'ul[lang="en"] .mw-thanks-thank-link a' )
+ .confirmable({ handler: function(){ alert('Thanked!') } });
+ </script>
+ <h3>RTL (Hebrew)</h3>
+ <!-- All of the Hebrew text below has been basically pulled out of my hat. -->
+ <p>Watchlist:</p>
+ <ul lang="he" dir="rtl">
+ <li class="mw-line-even mw-changeslist-line-not-watched">
+ (<a href="#">הבדל</a> | <a href="#">היסטוריה</a>)
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="mw-title"><a href="#" class="mw-changeslist-title">דף דוגמה</a></span>; <span class="mw-changeslist-date">13:38</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="mw-plusminus-neg">(-57)</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <a href="#" class="mw-userlink">דוגמא אדם</a>
+ <span class="mw-usertoollinks">(<a href="#">שיחה</a> | <a href="#">תרומות</a> | <a href="#">חסימה</a>)</span>
+ <span class="comment">(עריכה לדוגמה)</span>
+ <span class="mw-rollback-link">[<a href="">שחזור</a>]</span>
+ (<span class="mw-unwatch-link"><a href="#">הפסקת מעקב</a></span>)
+ </li>
+ </ul>
+ <p>History:</p>
+ <ul lang="he" dir="rtl">
+ <li>
+ <span class="mw-history-histlinks">(נוכחית | <a href="#">קודמת</a>)</span>
+ <input type="radio" style="visibility: hidden;" /><input type="radio" checked />
+ <a href="#" class="mw-changeslist-date">23:41, 12 במאי 2012</a>
+ <span class='history-user'>
+ <a href="#" class="mw-userlink">דוגמא אדם</a>
+ <span class="mw-usertoollinks">(<a href="#">שיחה</a> | <a href="#">תרומות</a> | <a href="#">חסימה</a>)</span>
+ </span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="history-size">(1,762 בתים)</span>
+ <span class="mw-plusminus-neg">(-57)</span>
+ <span class="mw-changeslist-separator">. .</span>
+ <span class="comment">(עריכה לדוגמה)</span>
+ (<span class="mw-rollback-link"><a href="">שחזור עריכה אחת</a></span> | <span class="mw-history-undo"><a href="#">ביטול</a></span> | <span class="mw-thanks-thank-link"><a href="#">תודה</a></span>)
+ </li>
+ </ul>
+ <script type="text/javascript">
+ var hebrewI18n = {
+ confirm: 'האם ברצונך להמשיך?',
+ yes: 'כן',
+ no: 'לא',
+ }
+ $( 'ul[lang="he"] .mw-rollback-link a' )
+ .confirmable({ i18n: $.extend( {}, hebrewI18n, { confirm: 'האם ברצונך לשחזר?' } ) });
+ $( 'ul[lang="he"] .mw-unwatch-link a' )
+ .confirmable({ i18n: hebrewI18n, handler: function(){ alert('Unwatched!') } });
+ $( 'ul[lang="he"] .mw-thanks-thank-link a' )
+ .confirmable({ i18n: hebrewI18n, handler: function(){ alert('Thanked!') } });
+ </script>
+ <style type="text/css">
+ /* This is normally handled by CSSJanus. */
+ ul[dir=rtl] .jquery-confirmable-button {
+ margin-left: 0;
+ margin-right: 1ex;
+ }
+ </style>
diff --git a/docs/uidesign/design.html b/docs/uidesign/design.html
index a285a5b2..51c1b552 100644
--- a/docs/uidesign/design.html
+++ b/docs/uidesign/design.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
- <link rel="stylesheet" href="../../skins/common/shared.css">
+ <link rel="stylesheet" href="../../resources/src/mediawiki.legacy/shared.css">
<body style="font-size: small;">