LLWiki正在建设中,欢迎加入我们

LLWiki:管理员技术手册

来自LLWiki
Bhsd讨论 | 贡献2023年3月17日 (五) 13:29的版本 (// 使用Wikiplus小工具快速编辑)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转到导航 跳转到搜索
内容缺失.png 此页面内容严重缺失,急需您帮忙补充!(点此编辑)
可参考同类条目添加所需内容,并从官方等可靠渠道搜集资料编写,亦建议附上资料来源。

由于LLWiki使用的不是最新版本的MediaWiki系统以及MediaWiki的帮助页面可能未得到及时和正确的更新,编辑这个页面时请不要简单地复制或翻译来自MediaWiki的内容,应该在条件允许的情况下先实际测试。

全站CSS

这里所说的全站CSS包含common.cssmobile.css和各CSS小工具,有时由于功能的相似性也会涉及用户CSS(common.cssvector.cssminerva.css)。LLWiki暂时没有建立针对不同用户组的专门CSS页面。

优先加载的CSS

一些CSS会以<link rel="stylesheet">的形式在首次渲染前完成加载,包括common.css和各纯CSS小工具,这些CSS页面适合处理静态HTML元素就需要的样式。注意纯CSS小工具即使在定义时规定了targets=mobile也一定会在桌面版加载,因此手机版的专用CSS需要添加.skin-minerva选择器。

由于common.css本身就会优先加载,桌面版专用的全站CSS写入该页面即可,与手机版通用的CSS写入gadget-site-styles.css。某个小工具专用的CSS如果需要用于静态HTML元素,请将CSS部分单独定义为type=styles(可省略,但添加后方便区分)的纯CSS小工具,然后以peers=<纯CSS小工具名称>的语法添加到对应的JS小工具上。参见#小工具定义

滞后加载的CSS

一些CSS的加载需要依赖JS,加载时机可能晚于首次渲染,包括mobile.css和除纯CSS小工具以外的CSS小工具,这些CSS页面适合处理依赖JS动态加载的HTML元素。

由于mobile.css加载滞后,静态HTML元素需要的手机版样式请添加.skin-minerva选择器后写入gadget-site-styles.css

CSS小工具分类

定义为type=styles的小工具应添加纯CSS小工具分类,其他CSS小工具应添加CSS小工具分类。其他分类与JS小工具一致,参见#小工具分类

Widget(小部件)

小部件页面格式

小部件分类

小部件JS的特殊之处

Gadget(小工具)和全站JS

这里所涉及的JS页面包含common.jsmobile.js和各JS小工具,有时由于功能的相似性也会涉及用户JS(common.jsvector.jsminerva.js)。LLWiki暂时没有建立针对不同用户组的专门JS页面。

ResourceLoader和JS模块

common.jsmobile.js用户JSMediaWiki:Gadgets-definition页面定义的小工具等JS页面会作为ResourceLoader的模块加载,这些JS将在语法检查和压缩后由load.php打包下载,且可以作为mw.loader.getState()方法、mw.loader.using()方法的参数。

作为ResourceLoader的模块加载时,不可使用ES6语法。这里的语法指关键字、算符等,不包括对象原型方法,例如Object.fromEntries()方法或new Map()构造器仍可照常使用。下表列出一些常见的JS模块不可使用的语法及其替代。

ES6以上语法 替代
=> output function() { return output; }
class NewClass extends Parent {
  constructor(params) { super(params); }
}
function NewClass(params) { NewClass.super.call(this, params); }
OO.inheritClass(NewClass, Parent);
{key} {key: key}
`firstline
secondline`
'firstline\n' + 'secondline'
`string${variable}` 'string' + variable
[variable] = array; variable = array[0];
{key: variable} = {key: value}; variable = {key: value}['key'];
function(params = defaults) function() { params = params || defaults; }
[...iterator] Array.from( iterator )
array2 = [...array1]; array2 = array1.slice();
[...array1, ...array2] array1.concat( array2 )
[element, ...rest] = array; element = array[0], rest = array.slice(1);
let[1] var
2**3[2] Math.pow(2, 3)
async function()[2] function() { return new Promise(resolve, reject); }
try { variable = await func(); } catch {}[2] func().then(function(result) { variable = result; }, function() {});
obj1 = {...obj2};[2] obj1 = $.extend(true, {}, obj2);
{...object1, ...object2}[2] $.extend(object1, object2)Object.assign(object1, object2)[3]

不作为模块的JS脚本

小工具定义

小工具简介

小工具分类

MediaWiki核心模块介绍

本章节介绍LLWiki使用或曾经使用的MediaWiki核心模块,更完整的列表参见MediaWikiJSDuck

mediawiki

mediawiki是任何页面都会预加载的两个环境模块之一,包含不少功能[4]。这里只介绍LLWiki常使用的一些属性和方法。

mw.config
这个属性提供了大量重要的站点、页面和用户信息[5],一般常用mw.config.get()方法获取对应的变量值。下表整理了LLWiki常用的一些变量:
变量名 说明 手机版可用性
skin 皮肤 桌面版为“vector”,手机版为“minerva”,这也是区分桌面版和手机版的主要依据
wgFormattedNamespaces 储存了所有命名空间本地化译名的数组,不过目前除了“模块”都是英文 可用
wgNamespaceIds 储存了所有可接受的中英文命名空间名称对应的编号,注意英文名称中的空格都显示为下划线 可用
wgScript /mediawiki/index.php,在LLWiki也可简化为/zh,主要用于不同MediaWiki站点间的代码通用,非必需且不推荐使用 可用
wgAction index.php的action参数[6] 相比于桌面版,手机版由于添加了Special:历史而少了“history”这个可能值
wgArticleId 内容页面编号,不存在时值为0,可以用于判断是否是内容页面且页面是否已建立 需要注意查看历史差异时值为0
wgCanonicalSpecialPageName 标准化的特殊页面名,也可被wgPageName取代,主要用于不同MediaWiki站点间的代码通用,非必需 可用,而且多了“History”和"MobileDiff"等可能的取值[7]
wgCategories 当前阅读的历史版本所属的分类,不含命名空间,下划线显示为空格,且总是包含隐藏分类。繁简规则遵从实际分类页面 仅LLWiki可用
wgCurRevisionId 页面最新的版本编号,不存在时值为0 历史差异页面不可用
wgIsArticle 是否是内容页面(包含由某个页面的Wikitext源代码解析生成的HTML,可能是历史页面和差异下方的历史页面) 由于差异页面不可同时显示历史页面,此时不可用
wgIsRedirect 最新版本是否是重定向页面 历史差异页面不可用
wgIsProbablyEditable 是否可能可以编辑 历史差异页面不可用
wgNamespaceNumber 命名空间编号 历史差异页面会显示为-1
wgPageContentModel 页面内容模型,特殊页面为“wikitext” 由于历史差异是特殊页面,会错误地显示为“wikitext”
wgPageName 页面名称,空格显示为下划线 历史差异页面不可用
wgRedirectFrom 跳转自重定向时为对应的重定向页,空格显示为下划线 可用
wgRelevantPageName 关联的页面名称,空格显示为下划线 可以用于历史差异页面,此时效果与桌面版一致
wgRelevantArticleId 关联的内容页面编号,不存在时值为0 可以用于历史差异页面,此时效果与桌面版一致
wgRelevantUserName 关联的用户名 用户贡献页面不可用
wgRelevantPageIsProbablyEditable 关联的页面是否可能可以编辑 可以用于历史差异页面,此时效果与桌面版一致
wgRestrictionEdit 编辑保护,不存在的页面(含受保护的标题)或特殊页面为null,存在的内容页面受全保护时为["sysop"],受半保护时为["autoconfirmed"],未保护为[];不包含命名空间保护和级联保护 历史差异页面不可用,另外未保护的内容页面为["*"]
wgRestrictionMove 移动保护,不存在的页面或特殊页面为null,存在的内容页面受全保护时为["sysop"],受半保护时为["autoconfirmed"],未保护为[];不包含命名空间保护和级联保护 历史差异页面不可用
wgRevisionId 当前显示的页面版本的编号,不存在时值为0。注意和index.php的oldid参数可能不同 由于差异页面不可同时显示历史页面,此时不可用
wgTitle 不含命名空间的页面名称,下划线显示为空格 历史差异页面不可用
wgUserEditCount 当前用户的编辑次数 可用
wgUserGroups 当前用户所属的用户组,未登入时为["*"] 可用
wgUserLanguage 当前用户使用的界面语言 可用
wgUserName 当前用户的用户名,下划线显示为空格 可用
wgUserRegistration 当前用户的注册时间,显示为毫秒数;可以使用mw.user.getRegistration()方法替代,该方法会生成Date对象 可用
wgUserVariant 当前用户阅读页面时的内容语言,在不可更改内容语言的页面总是为该用户的默认内容语言 可用
wgDiffOldId 差异页面位于左侧的版本的编号 不可用
wgDiffNewId 差异页面位于右侧的版本的编号 不可用
mw.hook()
这个方法是LLWiki建立异步JS框架的重要一环。常用以下两个方法:
  • mw.hook(hook).fire(data): 用于唤起一个Hook事件,其中data为传递给事件处理程序的可选参数。
  • mw.hook(hook).add(handler): 用于处理一个Hook事件,handler为该事件处理函数,参数传递自mw.hook().fire()方法。
这个方法应与jQuery的event delegation和各Promise对象结合使用,以在恰当的时机执行恰当的函数。以下列举LLWiki常用的Hook事件。
Hook名称 说明
MediaWiki预定义的Hook
postEdit 一次非空编辑提交成功,一般发生在自动重载页面后,可以搭配mw.config.get( 'wgPostEdit' )。需要注意各类编辑小工具提交编辑后的页面重载均未适配这个事件
structuredChangeFilters.ui.initialized 最近更改相关更改监视列表页面的过滤器加载完成,一般至多发生一次
wikipage.categories 页面下方的div#catlinks加载完成。特殊页面或没有添加任何分类时也能触发,因为此时#catlinks仍然存在只是隐藏起来
wikipage.collapsibleContent 某个或某组mw-collapsible类的元素添加折叠JS完成
wikipage.content 最常用的Hook,表示页面内容(一般即div#mw-content-text)加载完成,几乎无处不在,与$.ready最大的区别在于这个事件可能多次触发
wikipage.diff 差异(一般即table.diff)加载完成
wikipage.editform 编辑区加载完成,需要注意此时WikiEditor的工具栏可能尚未加载完成
codeEditor.configure 切换至CodeEditor
LLWiki定义的Hook
code.prettify 代码高亮完成
codemirror.config CodeMirror扩展的设置下载完成
hotcat.ready HotCat小工具加载完成
local.comments 签名时间替换为本地时区
to.bottom 添加滚动至底部的按钮
transclusion.preview 用于预览嵌入页面的编辑区加载完成
wikiplus.dialog 打开Wikiplus小工具的对话框
mw.loader
mw.loader包含了很多用于ResourceLoader的方法。
  • mw.loader.addStyleTag(),用于在header的末尾插入一个<style>。由于返回的是一个HTML元素,后续操作不如mw.util.addCSS()返回的StyleSheet对象方便,但在不需要后续操作的场合可以不用加载mediawiki.util模块。由于mediawiki.util在LLWiki的广泛使用,这个方法几乎没有任何优点。
  • mw.loader.getScript(),用于加载外部JS脚本,相比mw.loader.load()方法优点在于会返回一个Promise对象。
  • mw.loader.getState(),用于获取模块的当前状态,不可用的模块返回null,可用但未加载的模块返回'registered',可用且正在加载的模块可能返回'loaded''loading',已加载完成的模块返回'ready'。注意加载完成的模块未必已经执行完。
  • mw.loader.load(),用于加载模块、其他JS或其他CSS,加载模块时参数为模块名或一个模块名构成的数组,加载JS或CSS时填写url,加载CSS还需要额外填写第二参数'text/css'。缺点在于不会返回一个Promise对象。
  • mw.loader.using(),用于加载模块,相比mw.loader.load()方法优点在于会返回一个Promise对象,任一模块加载失败即返回rejected。
mw.notify()
调用这个方法可以在桌面版的右上角、手机版的上方显示一个泡泡通知。LLWiki一般使用这个方法取代window.alert()或OO.ui.alert()。
方法mw.notify(message, options)接受两个参数。第一个必需参数message指定通知内容,可以是字符串、HTML元素对象或元素对象数组、jQuery对象或mw.message对象;第二个可选参数options则指定自定义选项,是一个JS对象。
options中可自定义的选项有:
  • autoHide:布尔值,决定通知是否会自行消失。默认为true
  • autoHideSeconds:如果启用了autoHide(如默认情形),则指定通知自行消失的时间。默认为'short'(5秒),可以指定为'long'(30秒)。
  • tag:字符串,指定通知的标签,类似于HTML的ID。如果发送多个拥有同一个tag的通知,会导致之前的通知被后来的在原位覆盖。
  • title:标题。如果指定,则会于内容上方加粗显示。
  • type:字符串,指定通知的种类。除默认效果外其他可选类型为'success''warn''error'
mw.now()
这个方法理论上和Date.now()差不多,但实际测试表明和Date.now()的取值不同,因此请勿混合使用。非必需,基本可以完全被Date.now()替换。
mw.messages
用于改善代码结构,在代码开头使用mw.messages.set()方法结合wgULS()和wgUCS()设置自定义消息的繁简名称,然后使用mw.msg()方法即可调用。使用这一方法时,还能以$1的形式设置待定参数,或使用部分解析器函数。

jquery

jquery是任何页面都会预加载的两个环境模块之一,尤其在DOM操作和Ajax请求方面功能强大,非常推荐在JS编程之前预先熟悉API文档。考虑到mw.loader已经集成了不少的常用Ajax方法,这里主要推荐熟练掌握DOM相关的内容,包括事件DOM操作选择器遍历。特别需要提醒的是滥用htmlString有造成XSS的风险,因此请尽量使用如$('<p>', {html: $('<a>', {text: '文字', href: 'https://llwiki.org'})})$('<p>').append( $('<a>').text('文字').attr('href', 'https://llwiki.org') )等语法进行规避。

因未被mw.loader包含而可能用到的Ajax方法主要为$.getJSON(),需要注意在MW的默认设置下调用jQuery的Ajax方法必须手动设置{cache: true}

另外jQuery也提供了一些工具方法,可以用于缓解ResourceLoader的JS模块不允许使用ES6语法的问题,或是方便键值对相关的语句的书写,或是方便连锁。比如用$.extend()方法代替...算符、用$.each(obj, (key, val) => {})方法代替for (const key in obj) {}等。

应用jQuery时可能出现的一些常见错误列举如下:

  • 混淆.attr()方法和.prop()方法。
  • 混淆jQuery对象的.data()方法和HTML元素的.dataset属性。
  • 使用.toggle().fadeToggle()等方法时不慎破坏较复杂的CSS布局。
  • 错误使用.remove().clone()等方法造成丢失数据和事件处理程序。
  • 混淆event.targetevent.currentTargetevent.delegateTargetthis关键字。
  • 混淆$.when()方法和Promise.all()方法的参数格式和回调函数。

mediawiki.api

这个模块提供了一系列方法用于简化API请求。使用这一模块时,需要首先建立一个mw.Api对象,常用语法为const api = new mw.Api();。以下列举这个mw.Api对象常用的方法,没有出现在以下列表中的方法可能不仅是不推荐使用,而是因为未适配中文的繁简转换而不应在LLWiki使用。

  • api.get(),这是最基础的两个方法之一,用于提交类型为GET的Ajax请求,参数基本与api.php的参数一致,区别在于返回的格式已经限定为JSON对象,即可省略参数{action: 'query', format: "json"}。API请求的参数列表详见API文档,这里特别推荐一下generator参数[8]的强大功能和{formatversion: 2}这个参数。
  • api.post(),这是最基础的两个方法之一,用于提交类型为POST的Ajax请求,用法与api.get()方法高度相似。一般情形下,{action: 'query'}的请求应该使用api.get()方法以充分利用浏览器缓存等优点;但如果请求的数据量过大,可能不得不使用api.post()方法代替。
  • api.postWithToken(),提交改动时一般使用这个快捷方法而非传统的api.post(),但在很多情形下都可以替换为下述更为方便的方法,只有用于{action: 'patrol'}时难以替代。
  • api.postWithEditToken(),相当于api.postWithToken('csrf', params),主要用于提交编辑。大部分情况下不推荐使用api.edit()方法替代,因为api.edit()在大多数应用场合会造成重复而不必要的{action: 'query', prop: 'revisions'}请求。为了避免编辑冲突,在LLWiki请尽可能使用mw.safeEdit()方法。另外在建立新页面({createonly: 1}或直接应用api.create()方法)时,请务必先检查对应的繁简中文标题是否已经存在。
  • api.newSection(),这个方法相比api.postWithEditToken()可以进一步简化添加新章节的代码。
  • api.rollback(),相当于api.postWithToken('rollback', params),用于回退。
  • api.watch(),相当于api.postWithToken('watch', params),用于监视。
  • api.unwatch(),相当于api.postWithToken('watch', params),用于取消监视。
  • api.upload(),相当于api.postWithEditToken()的{action: 'upload'}。注意这个方法只能上传本地文件,需要通过url上传的请使用api.postWithEditToken()方法。
  • api.parse(),用于解析HTML的快捷方法,常用于生成预览。如果要获得现存页面的HTML,还需要加载mediawiki.Title,此时建议可以直接使用标准的api.get()方法代替。

mediawiki.util

mediawiki.util提供了很多非常方便的方法,可以用于满足形形色色的需要。这个模块会在加载很多其他模块时加载,如mediawiki.api、mediawiki.Title和mediawiki.Uri等。

  • mw.util.addCSS(),相比mw.loader.addStyleTag()方法,因为返回值是一个StyleSheet对象而更便于后续动态操作。
  • mw.util.addPortletLink(),实际上并不如直接使用jQuery自由度更大,但这个方法可能会出现在一些从其他维基导入的小工具里,不推荐使用。
  • mw.util.debounce(),这个方法用于降低一个函数被调用的频率,常见的比如scroll事件。
  • mw.util.escapeRegExp(),mw.util还有其他的转义方法[9],但应用较少,不再赘述。
  • mw.util.getParamValue(),提取php参数,能够满足可能存在的各种奇怪情形,不建议使用自己写的正则匹配替代。
  • mw.util.getUrl(),获取页面对应的相对网址,一般来说使用mw.config.get('wgScript') + '/' + pageName即可。但如果页面名称中含需要转义的字符(如?&),使用这个方法还是挺方便的。
  • mw.util.wikiUrlencode(),非常好用的方法,相比encodeURIComponent不会转义:/,相比encodeURI则增加了对?&的转义,是转义页面名称的最佳选择,同时在用做url时也比mw.util.getUrl()方法有更大的自由度。

mediawiki.Uri

除了可以替代mw.util.getParamValue()方法用于获得URI的各项参数,mediawiki.Uri还可以方便地修改或生成URI。使用时首先需要应用const uri = new mw.Uri(str, options);语法来构建一个mw.Uri对象,强烈推荐在options中设置{overrideKeys: true}以免后续出现未预期的JS语法错误。

  • uri.fragment,获得#后的章节名。
  • uri.host,在LLWiki总是为'llwiki.org'
  • uri.path,在LLWiki的内容页面一般总是为'/zh''/mediawiki/index.php'(两者等效)。
  • uri.protocol,在LLWiki总是为'https'
  • uri.query,包含了所有php参数的JS对象,在规定了{overrideKeys: true}时每个值都是字符串,否则重复参数的值为数组。
  • uri.clone(),复制mw.Uri对象。
  • uri.extend({key: value}),添加或覆盖php参数,这在URI以#结尾时非常方便。如果需要删除php参数的话,可以直接使用delete uri.query.param的语法。
  • uri.getQueryString(),获得整个php请求字符串。
  • uri.getRelativePath(),获得相对地址。
  • uri.toString(),获得包含协议的绝对地址。

mediawiki.Title

彻底解决关于页面名称或文件名称的各种烦恼,包括大小写、空格/下划线、命名空间别名等等。通常用法为先使用const title = new mw.Title(str);的语法构建一个mw.Title对象。与mw.util的很多方法以及new mw.Uri()不同,new mw.Title(str)不会以当前页面作为默认参数。因为未统一大小写、空格/下划线等,请勿直接访问title.title属性,而是根据需要使用下列方法。

  • title.getExtension(),获取文件名的扩展名。
  • title.getFragment(),如果页面名称中含#,获取章节名。也可以直接使用title.fragment属性访问。
  • title.getMain(),获取页面名,首字母大写,空格替换为下划线。
  • title.getMainText(),获取页面名,首字母大写,下划线被替换为空格。
  • title.getName(),获取文件名,不含扩展名,首字母大写,空格替换为下划线。
  • title.getNameText(),获取文件名,不含扩展名,首字母大写,下划线替换为空格。
  • title.getNamespaceId(),获取命名空间,能识别一切别名。也可以直接使用title.namespace属性访问。
  • title.getNamespacePrefix(),获取标准命名空间前缀,含:
  • title.toString(),获取完整页面名称,命名空间使用标准前缀,不含#,空格替换为下划线。
  • title.toText(),相比title.toString()方法,下划线替换为空格。
  • title.getRelativeText(nsid),相比title.toText()方法,会命名空间编号匹配时移除命名空间前缀。
  • title.getSubjectPage(),生成讨论页对应的主页面的mw.Title对象。
  • title.getTalkPage(),生成对应的讨论页的mw.Title对象。
  • title.getUrl(),生成地址,可以添加JS对象格式的php参数。
  • title.isTalkPage(),是否是讨论页。

此外,mediawiki.Title还有一些静态方法用于生成mw.Title对象。

  • mw.Title.makeTitle(nsid, title),给定命名空间编号和标题生成对象。不存在的命名空间会报错。仅当命名空间为0时,会根据标题生成正确的命名空间。
  • mw.Title.newFromFileName(filename),给定文件名生成对象。
  • mw.Title.newFromImg(node),给定<img>节点或对应的jQuery对象生成mw.Title对象。
  • mw.Title.newFromText(title, nsid),相比mw.Title.makeTitle()方法,错误的命名空间编号也不会报错,且当标题含命名空间前缀时总是覆盖第二个命名空间参数。

mediawiki.storage

mediawiki.storage提供了处理localStorage或sessionStorage的便利方法。注意出于安全性的考虑,请勿使用localStorage存储用户的个人信息。mw.storage对象对应localStorage,mw.storage.session对象对应sessionStorage,这两个对象拥有相同的方法,所以以下只介绍mw.storage对象。

  • mw.storage.get(),相当于localStorage.getItem()方法,所以使用价值不高。
  • mw.storage.set(),相当于localStorage.setItem()方法,所以使用价值不高。
  • mw.storage.remove(),相当于localStorage.removeItem()方法。
  • mw.storage.getObject(),相当于JSON.parse( localStorage.getItem(key) )
  • mw.storage.setObject(),相当于localStorage.setItem(key, JSON.stringify(value))

user.options

用于方便地获取用户设置。

  • mw.user.options.values,存储了所有用户设置。
  • mw.user.options.get()方法,用于获取特定用户设置。比如想获取用户有无启用某一小工具,可以使用mw.user.options.get( 'gadget-name' )方法。如果不想加载user.options模块,也可以使用['loaded', 'loading', 'ready'].includes( mw.loader.getState( 'ext.gadget.name' ) )代替,但两者会因手动加载小工具(如mw.loader.load( 'ext.gadget.name' )或在手机版检查仅在桌面版注册的小工具而产生差异。

下表整理了一些JS中常用的用户设置,完整列表请参阅MediaWiki

设置名 说明
date 日期格式
timecorrection 时区
multimediaview-enable 启用媒体查看器
diffonly 差异下方不显示页面内容
norollbackdiff 回退不显示差异
showhiddencats 显示隐藏分类
numberheadings 标题自动编号
showrollbackconfirmation 回退确认
editsectiononrightclick 右键段落编辑
editondblclick 双击编辑
minordefault 默认小编辑
useeditwarning 提示未保存的编辑
usebetatoolbar 使用WikiEditor的增强工具栏
previewontop 在编辑框上方显示预览
uselivepreview Ajax预览
extendwatchlist 监视列表显示所有更改
rcenhancedfilters-disable 禁用最近更改过滤器
wlenhancedfilters-disable 禁用监视列表过滤器

jquery.makeCollapsible

用于折叠.mw-collapsible类,使用语法非常简单。

jquery.tablesorter

用于table.sortable的排序,使用语法非常简单。

jquery.textSelection

用于快速处理textarea相关的操作。比如CharInsert扩展就是主要基于这个模块开发的。

  • textSelection(command, [options])方法,以下所有指令均借助这一方法执行。
  • 'encapsulateSelection',在选中的文字前后插入文字。
  • 'getCaretPosition',获取光标位置。
  • 'getSelection',获取选中文字。
  • 'replaceSelection',替换选中文字。
  • 'scrollToCaretPosition',滚动到光标位置。
  • 'setSelection',设置选中区域。

jquery.client

用于查询用户设备和浏览器的相关信息,相比直接使用navigator,这个模块使用起来更加简便和友好。这个模块会在加载mediawiki.util时加载。

  • const profile = $.client.profile();,以对象的形式输出设备和浏览器信息。
  • profile.platform,可识别的设备类型:iphone、linux、mac、win。
  • profile.name,可识别的浏览器类型:android、chrome(包括手机chrome、edge、opera等)、iphone、edge(旧版edge)、firefox(包括手机firefox)、opera(旧版opera)、safari等。
  • profile.layout,可识别的引擎类型:edge、gecko、konqueror、opera、trident、webkit。

jquery.color

可以进行CSS颜色的十六进制、RGB和HSL的转换或计算亮度,但因为这个模块在手机版未注册,请谨慎使用。如确有必要在手机版调用此模块,请联系有后台访问权限的管理人员。

jquery.ui

jquery.tipsy

用于统一tooltip的显示样式,使用语法非常简单,同时效果也相比一些浏览器的默认行为更加美观和醒目。然而这个模块并未在手机版注册,同时对窄屏的适配也欠佳,因此请替换为mw.tipsy()方法

jquery.chosen

用于将select元素转化为combo box,语法非常简单,但该模块未在手机版注册,请替换为OO.ui.ComBoxInputWidget对象。

jquery.confirmable

用于以内联形式添加一个确认步骤,需要根据使用场所调整需要的CSS,也因此用起来相对繁琐。另外这个模块也未在手机版注册,请替换为mw.confirm()方法

oojs-ui-core

对于各种用于用户交互的HTML元素,如<button>、<select>、<input>等,不同浏览器往往会默认添加不同的样式。为了统一这些表单元素的外观,MediaWiki的界面UI大多基于OOUI设计,oojs-ui-core则包含了OOUI的最基本元素。这些元素往往借助<div>等基本HTML元素和CSS/JavaScript模拟出表单元素的效果。下表列出oojs-ui-core中供直接使用的对象实例:

对象实例 说明
ActionFieldLayout 包含一个输入元素、一个按钮和一个可选的帮助信息
ButtonGroupWidget 可包含一组ButtonWidget
ButtonInputWidget 用于FormLayout的按钮
ButtonWidget 最基础的按钮
CheckboxInputWidget 复选框,最好置于设置为{align: 'inline'}的各种layout内
CheckboxMultiSelectInputWidget 用于FormLayout的真正意义上的“复选框”
CheckboxMultiSelectWidget 真正意义上的“复选框”
ComboBoxInputWidget 既可键盘输入,又可选择选项
DecoratedOptionWidget 用于SelectWidget的带图标的选项
DropdownInputWidget 用于FormLayout的下拉选单
DropdownWidget 下拉选单
FieldLayout 包含一个输入元素和标签或帮助信息
FieldSetLayout FieldLayout的组合
FormLayout 用于构建表单
HorizontalLayout 行内样式的layout
HtmlSnippet 用于插入htmlString
IconWidget 图标
IndicatorWidget 另一种小图标
LabelWidget 标签
MultilineTextInputWidget 相当于textarea
NumberInputWidget 带增减按钮的输入仅限数字的文本框,由min/max/step/required设置代替validate设置
PanelLayout 占据整个父容器的layout
PopupButtonWidget PopupWidget的开关
PopupWidget 相当于tooltip
ProgressBarWidget 进度条
RadioInputWidget 一个单独的单选框,一般下不应使用
RadioSelectInputWidget 用于FormLayout的单选框
RadioSelectWidget 单选框
SearchInputWidget 搜索框
SelectFileInputWidget 上传本地文件,不可拖拽
TextInputWidget 文本框

oojs-ui-windows

oojs-ui-windows在oojs-ui-core的基础上补充了各类对话框及相关元素。下表列出了oojs-ui-windows添加供直接使用的对象实例:

对象实例 说明
ActionWidget 用于对话框的按钮
Dialog 最基础的对话框,所有对话框均必须使用WindowManager打开,且大部分无法直接使用
MessageDialog 消息对话框,唯一一种可直接使用的自定义对话框
ProcessDialog 进程对话框,无法直接使用
WindowManager 用来打开各种对话框
OO.ui.alert() 相当于window.alert(),但手机版的CSS设计有缺陷,请使用mw.notify()方法替代
OO.ui.confirm() 相当于window.confirm(),但返回的是Promise对象
OO.ui.prompt() 相当于window.prompt(),但返回的是Promise对象

oojs-ui-widgets

oojs-ui-widgets在oojs-ui-core的基础上补充了一些更复杂的元素。下表列出了oojs-ui-widgets添加供直接使用的对象实例:

对象实例 说明
BookletLayout 左侧分页布局
ButtonMenuSelectWidget 点击按钮展开下拉选单
ButtonSelectWidget 使用按钮的单选框
IndexLayout 分页
MenuLayout 同时包含了菜单和内容
MenuTagMultiselectWidget 使用菜单进行多选
PopupTagMultiselectWidget 使用气泡输入的多选
SelectFileWidget 选择文件
StackLayout 堆叠布局
TagMultiselectWidget 使用文本输入生成标签多选,是MenuTagMultiselectWidget和PopupTagMultiselectWidget的基础类型
ToggleButtonWidget 使用按钮开关
ToggleSwitchWidget 开关

mediawiki.widgets

LLWiki添加的全局变量和方法

window.wgULS(hans, [hant])window.wgUCS(hans, [hant])[10]
用于处理繁简文字信息,wgULS()用于界面语言,wgUCS()用于内容语言。为方便维护,在大量使用繁简转换的页面,请将所有繁简文字以mw.messages.set()方法的形式至于代码开头,然后在使用时以mw.msg()方法调用即可。
mw.gadgets
这个对象储存了所有小工具的设置。
mw.request
这个对象储存了一个mw.standardQuery()方法返回的Promise对象,即获取当前版本全文Wikitext的API请求。
mw.sections
这个数组的每一项对应一个mw.sectionQuery()方法返回的Promise对象,即获取对应段落Wikitext的API请求。
mw.widget
这个对象储存了小部件的执行情况,防止Ajax预览造成小部件重复执行。
mw.settingsDialog[11]
这个对象是一个SettingsDialog类,用于小工具设置的图形界面。这个类提供了多种方法,包括:获取小工具名称(getName)、获取小工具对象(getObject)、获取小工具标签页(getPanel)、添加小工具(addTab)、生成设置对象(generateOptions)、将设置保存到localStorage(saveOptions)、还原设置(clearOptions)和导出设置(export)。用法复杂,详见代码页
mw.pagenamee()[10]
这个方法用于获取转义后的当前页面名称。需要mediawiki.util。
mw.addMobileLinks(link)[10]
这个方法生成手机版菜单需要的列表构成的数组,可以随后加入DOM中。link为对象或对象数组,每一项包含链接地址href(可选)、FontAwesome图标icon(默认为圆圈包裹的一个向右箭头)、文字信息text(需要手动设置繁简转换,优先级低于msg)或mw.messages的键值msg和<li>元素属性attr(可选)。
mw.isModule(name, [flag])[10]
这个方法用于检测一个模块是否正在或已经加载。name为模块名或小工具名;flag为真时自动在小工具名name前添加前缀'ext.gadget.'
mw.apiFailure(reason, topic)[10]
这个方法用于输出一个API请求失败的气泡通知。reason为API返回的错误信息,一般来自状态为reject的API请求;topic为简短的文字说明,需要手动设置繁简转换。
mw.timedQuery(api, params, topic)[10]
这个方法用于提交一个可自定义的API请求,并记录用时,失败时应用mw.apiFailure()方法生成气泡通知并抛出错误。api为一个mw.Api对象;params即API参数,默认已填入{action: 'query', formatversion: 2},可以覆盖;topic为简短文字描述,需要手动设置繁简转换。需要mediawiki.api。
mw.timedParse(api, params, topic)[10]
Ajax使用POST而非GET,因此适合预览大段Wikitext。params的默认设置为{action: 'parse', prop: 'text', title: mw.config.get( 'wgPageName' ), disablelimitreport: 1, disableeditsection: 1, pst: 1, formatversion: 2},可以覆盖。填入page、pageid或oldid参数时请勿使用此方法,应当选用包含{action: 'parse'}参数的mw.timedQuery()。topic同样需要手动设置繁简转换。需要mediawiki.api。
mw.standardQuery(api)[10]
使用mw.timedQuery()方法提交一个API请求以获取当前版本的全文Wikitext并保存至mw.request。需要mediawiki.api。
mw.sectionQuery(api, section, [force])[10]
使用mw.timedQuery()方法提交一个API请求以获取段落Wikitext并保存至mw.sections。section为段落编号,默认为序言;为降低错误编辑历史版本的风险,想要获取历史版本的段落Wikitext时,必须手动添加为真的force参数。需要mediawiki.api。
mw.safeEdit(api, curRevid, params, [flag])[10]
检查有无编辑冲突后提交编辑。api为mw.Api对象;curRevid为当前最新版本的编号,默认为mw.config.get( 'wgCurRevisionId' );parmas为API参数,默认为{action: 'edit'},可以覆盖,但原则上请勿使用这一方法执行其他操作;flag参数对应是否开启自动备份小工具,这会改变检测到编辑冲突时的错误通知。检测到编辑冲突抛出错误'editConflict',API请求失败抛出错误'editFailure''revisionQueryFailure'。需要mediawiki.api。
mw.safeRedirect(api, title, target, [summary])[10]
检查繁简转换后的页面是否已经存在后创建新重定向。api为mw.Api对象;title为重定向页标题;target为重定向目标页标题,默认为当前页面;summary为可选摘要。页面已存在时抛出'pageExists',API请求失败时抛出'createFailure''queryFailure'。需要mediawiki.api。
mw.confirm(text, [flags])[10]
借助OO.ui.confirm()方法生成一个确认对话框。text为确认提示,可以是字符串或jQuery;flags为确认键的样式数组,可选元素包括'primary''progressive''destructive',其中'primary'不能单独生效。返回值为一个状态为resolve的Promise对象,值为真表示确认。需要oojs-ui-windows。
mw.prompt(text, [flags], [config])[10]
借助OO.ui.prompt()方法生成一个prompt对话框。text为文字提示,可以是字符串或jQuery;flags为确认键的样式数组,可选元素包括'primary''progressive''destructive',其中'primary'不能单独生效;config为可选的文本框设置。返回值为一个状态为resolve的Promise对象,值为null表示取消。需要oojs-ui-windows。
mw.dialog(dialog, actions, $message, [$title])[10]
借助OO.ui.MessageDialog对象生成一个更复杂的对话框。dialog为预先准备的OO.ui.MessageDialog对象;actions为OO.ui.ActionWidget对象构成的数组;$message为提示信息,相比mw.confirm()方法的进步之处在于可以使用jQuery或htmlString;$title为对话框标题。返回值为点击按钮时的Promise对象。需要oojs-ui-windows。
mw.tipsy($container, [target], [params], [$content])[10]
借助OO.ui.PopupWidget对象生成一个手机版也有效的tooltip。$container为外部容器的jQuery对象(不能是body);target为目标元素的选择器;params为建立OO.ui.PopupWidget对象时的参数,默认为{padded: true, width: null, classes: ['mw-tipsy']},可以覆盖;$content为自定义的tooltip内容,默认为title或data-title属性。需要oojs-ui-core。
mw.menu(options, [config], [unselectable])[10]
借助于OO.ui.MenuSelectWidget生成一个浮动菜单。options为选项数组,每一项包含文本text(需要手动设置繁简转换)、FontAwesome图标icon(可选)、数据data(可选)、链接href(可选)和点击事件click(可选);config为菜单设置,默认为{classes: ['site-menu'], hideWhenOutOfView: false},可以覆盖;unselectable为真时,菜单不会保留之前最后一次的选择记录。这个UI方法的用法较为复杂,详见代码页
mw.convertTimezone(then, timezone)[10]
改变moment对象的时区。then为待处理的moment对象,默认为现在;timezone为时区的IANA名称或数值表示的UTC偏移量,需要提前检查合法性,默认为本地时区。注意这个方法的返回值不是一个真实存在的时间点,只能用于输出而不能用于进一步运算。需要moment。
mw.resizeLyrics()[12]
重新计算.Lyrics_box的大小,并调整原文和译文的排列方式。

JSHint

CodeEditor使用JSHint标注可能存在的语法问题。LLWiki会在大部分JS页面添加JSHint设置/* global mw *//* jshint jquery: true, bitwise: true, curly: true, latedef: 'nofunc', nonew: true, singleGroups: true, unused: true */[13]。但在小部件页面,为了提示小部件JS加载在模块mediawiki和jquery之前,/* global mw *//* jshint jquery: true */被替换为/* jshint varstmt: true */。注意JSHint并不会对大多数JS模块不允许使用的ES6语法作出警告(详见#ResourceLoader和JS模块),因此请勿过度依赖这一功能来除错。另外CodeEditor安装的JSHint版本较老,无法识别ES7以上的语法,因此在代码中使用ES7语法可能会造成除错时的困难。

注意事项

手机版

手机版解析器

图片懒加载

手机版CSS

手机版LLWiki使用Minerva Neue皮肤,与桌面版的Vector皮肤相比,不仅界面有很大差异,众多基础HTML元素也都添加了不同的CSS样式。为了适配窄屏设备,Minerva皮肤还添加了大量基于@media的规则,一般以设备宽度720px为分界使用不同的样式。以下着重介绍<table><img>这两种需要CSS修正的重灾区。

手机版CSS很多时候依赖外层容器的content类来生效,与此同时#mw-content-text .mw-parser-output的外层结构也同样有效,设计各种基于API的快速编辑工具(如Wikiplus等)的预览界面时需要考虑。

表格

对于<table>元素及其子节点,手机版已知会自动添加以下样式:

table, caption, tbody, tfoot, thead, tr, th, td {
	font-size: 100%;
}
table {
	border-collapse: collapse;
}
.content table {
	margin: 1em 0;
	overflow: auto;
	overflow-y: hidden;
	overflow-x: auto;
}
@media only screen and (max-width: 720px) {
	.content table {
		display: block;
		width: 100% !important;
	}
}

这里重点说明一下第二和第四条规则造成的影响。第二条规则使得表格的外层边框、行边框和单元格边框合并,可能造成一系列关于边框的CSS规则出现不符合预期的表现,尤其是<table>cellspacing属性会无法生效。因此一般建议避免使用cellspacing这一HTML属性,改为使用CSS中的border-spacing。另外,在需要border-spacingborder-radius等样式时,请同时指定border-collapse: separate;以使手机版生效。

第四条规则的本意是在窄屏上<table>元素不会将页面撑得过宽,但这同时会造成外层的<table>和内层的<tbody>分离。特别是如果外层<table>规定了边框或背景色时,很容易看出样式的错误。为此一般需要主动指定display: table;以修复这一问题,LLWiki有很多预定义的表格CSS类也都添加了这一规则[14]。但这样修改的话又会重新面临过宽的表格将整个页面撑大的问题。LLWiki现定义了table-wrapper[14],用于套在宽表格外:<div class="table-wrapper">,这个外层容器会在窄屏上通过overflow-x: auto;限制里面的表格宽度。

图片

皮肤界面

其他

手机版JS

手机版JS模块

繁简转换

Wikitext繁简转换

转换表

Template:NoteTA

基本手工转换语法

系统消息

CSS繁简转换

JS繁简转换

滥用过滤器

测试账户

如果管理员需要一个没有自确权限的测试账户用于滥用过滤器测试、小工具测试等,可以临时启用6号滥用过滤器来移除某个测试账户的自确权限。这个滥用过滤器的使用语法非常简单,请根据样例修改为对应的用户名即可,这里不再赘述。

参考资料

  1. const可用。
  2. 2.0 2.1 2.2 2.3 2.4 ES7以上语法虽然在不作为ResourceLoader的模块时允许使用,但因为CodeEditor安装的JSHint版本不支持语法分析,可能会造成代码除错时的困难。
  3. 注意$.extend()方法与另两者并不完全一致,但更推荐使用$.extend()。
  4. MW:ResourceLoader/核心模块
  5. 完整列表
  6. 完整参数列表
  7. 移动前端的扩展说明
  8. API文档(action = query)
  9. mw.util文档
  10. 10.00 10.01 10.02 10.03 10.04 10.05 10.06 10.07 10.08 10.09 10.10 10.11 10.12 10.13 10.14 10.15 10.16 需要加载site-lib.js
  11. 需要加载SettingsDialog.js
  12. 需要加载Widget:Lyrics
  13. 新版JSHint的设置列表,注意可能存在的版本差异。
  14. 14.0 14.1 全站CSS