灰机版本 > 2.1.0

MediaWiki因为安全问题,所支持的HTML标签有限,这造成了一些设计上的困难。为了解决这些困难,并且不放弃安全性,灰机wiki增加了HTML命名空间。该空间只对拥有开发者权限的用户开放。

在HTML命名空间内,除了支持撰写原生的HTML5,还额外增加了Mustache模板支持。Mustache模板是一款短小精悍而又灵活多变的Web模板引擎。他的语法和MediaWiki有诸多相似之处,而且可以被Wikitext、PHP、Javascript、Lua同时调用。

为了避免Mustache模板生成的代码被MediaWiki解析器干扰,生成的结果会被压缩为单行,并且在前后加上注释标记。

使用wikitext调用

在HTML命名空间下创建一个页面Html:Test,其内容为:

Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
Well, {{taxed}} dollars, after taxes.
{{/in_ca}}

调用

{{#html:Test |name=Chris |value=10000 |taxed={{#expr:10000 - (10000 * 0.4)}} |in_ca=true }}

效果

Hello ChrisYou have just won 10000 dollars!Well, 6000 dollars, after taxes.

在Mustache模板中使用wikitext

在V2.1.0更新后,Mustache模板中可以使用wikitext,代码如下:

{{#wt}}在这里添加wikitext{{/wt}}

由于Mustache的{{}}依然会优先于wikitext解析,最好不要在Mustache模板中添加wikitext模板,这种方法可以用于添加内链或图片。

如需要内嵌其他模板,可以使用Mustache的partial方式,内嵌另一个Mustache模板,调用方法是{{>模板名称}}。

使用Javascript调用

调用

mw.loader.load('mediawiki.template.mustache');
$.get('http://www.huijiwiki.com/wiki/Html:Test?action=raw').done(
	function(raw){
		var template = mw.template.compile(raw, 'mustache');
		var html = template.render({
			name: 'Chris',
			value: 10000,
			taxed: 10000 - (10000 * 0.4),
			in_ca: true
		});
		$('#mw-content-text').append(html);
	}
);

在浏览器的控制台粘贴部分代码,就可以在本页看到结果。

使用Lua调用

方法1:通过Lustache

使用限制

在Lua调用的情况下,生成的结果仍然需要经过mediawiki解析器处理。所以,<a>、<img>等标签依然会被过滤掉。

此部分需要借助Lustache库。灰机并没有打包该库,但是通过Template Manager你可以将该库一键导入后使用。导入Lustache到任一维基

local p = {}

function p.render(frame)
	local lustache = require "Module:Lustache"

	view_model = {
	  name = "Chris",
	  value = 10000,
	  in_ca = true,
	  taxed = function ()
	    return 10000 - (10000 * 0.4)
	  end
	}

	local title = mw.title.new( 'Test', 'Html' )
	return lustache:render(title:getContent(), view_model)
end

return p

方法2:通过灰机内置函数

灰机打包的函数mw.ext.mustache可以处理Mustache模板,并且直接生成HTML,不会再被Parser处理,因此可以直接生成某些Wikitext禁止的标签。

local p = {}
 
function p.render(frame)
	view_model = {
	  name = "Chris",
	  value = 10000,
	  in_ca = true,
	  taxed = 10000 - (10000 * 0.4)
	}
 
	return mw.ext.mustache.render('Test', view_model)
end

return p
 

mw.ext.mustache.render(templateName, args, flag)

mw.ext.mustache.render的第3个参数是一个flag(可不填,默认为false)。

mw.ext.mustache.PERSERVE_KEY

如果该flag未填写,则自动将第二个参数args从1开始的数组(欢迎来到Lua!)转换成0开始的数组,以符合mustache需要。如果你需要手动处理args的键值,应该将此参数设为mw.ext.mustache.PERSERVE_KEYS。

mw.ext.mustache.PARSE_ARGS

如果未填写此flag,则所有args中的参数不会经过维基parser处理,也就是[[ABC]]将不会被转换成A标签。如果填写的话,[[ABC]]会变为<a href="/wiki/ABC">ABC</a>。

高级使用

Mustache可以用于处理数组等复杂的数据结构。 对于Html:Test2:

{{#repo}}
  <b>{{name}}</b>
{{/repo}}

调用

使用{{#html:Test2|repo..name=Jon|repo..name=Dany|repo..name=Tyrion}}可以得到:

结果

JonDanyTyrion

解释

为了更好的利用Mustache,#html解析器会依照下列格式构建一个参数树状结构。

参数格式 PHP示意 JSON示意
a array( a => true ) {a:true}
a.b array( a => array( b => true ) ) {a:{b:true}}
a.b.c array( a => array( b => array( c => true ) ) ) {a:{b:{c:true}}}
a = bob array( a => bob ) {a: "bob"}
a.b=cat array( a => array( b => cat ) {a: {b:"cat"}}
a.b=cat

a.d = frog

array( a => array( b => cat, d => frog ) ) {a: {b: "cat", d:"frog"}}
a.b=cat

a.b=dog

array( a => array( b => array ( cat, dog ) ) ) {a:{b:["cat, "dog"]}}
a..b=cat array( a => array ( array( b => cat ) ) {a:[{b:"cat"}]}
a..b=cat

a..b=dog

array( a => array( array ( b => cat ), array( b => cat) ) ) {a:[{b:"cat"}, {b:"dog"}]}

可视化编辑

目前,可视化编辑器在保存时会去掉重复的参数,这导致#html无法处理a..b=cat a..b=dog之类的情况。解决方法是将#html封装到一个模板中,不要直接在允许可视化编辑的内容页面使用。

对于更多详情,请参阅:https://mustache.github.io/mustache.5.html

案例

可参阅Html:TableModule:Table,通过Mustache模板定义了数据和表格的对应关系。

已知的限制

  • <a>标签内不能直接插入div,这是MediaWiki的限制,建议用span替代。即使不用Mustache模板,使用[[Link|<div>link</div>]]和[[Link|<span>link</span>]]的结果也不相同。
  • 如果在HTML中直接使用<script>标签,那么内容中的代码会在DOM ready之前执行,该时刻JQuery还没有加载。如果想用JQuery,可以使用
<script type="text/javascript">
RLQ.push(function () {
    console.log('This runs with jQuery support', $);
});
</script>
  • 不能用阿拉伯数字作为Mustache模板的参数名。

规避风险

<div class="{{{arg}}}"></div>

上述代码存在严重风险,任何具有普通编辑权限的人将可以注入任意代码。在标签内使用参数时,请注意一定要使用双大括号而不是三大括号。上述代码应改为:

<div class="{{arg}}"></div>

此外,如果有开发者的Mustache模板中存在

<script>console.log({{stuff}});</script>

这种明显的漏洞,将会被立刻吊销开发者资格。

avatar
avatar
0
还是有点小问题,只要换行了,就容易被套个

标签

3个月
avatar
Reasno
0

fixed in 2.0.27

3个月
avatar
Icicle
0

我的0.315test和0.316test都没调用出来 还有就是帮助:模块页面糊掉了

4个月
avatar
Honestleaf
0

你需要@Reasno,在页面下回复他看不到的。

4个月
avatar
Icicle
0

回复@Honestleaf:我不是特别急,反正他有回复你嘛:see_no_evil:

4个月
avatar
Honestleaf
0

回复@Icicle::smile:那是因为我先回复他了啊。如果不@或者回复留言,对方就收不到提醒邮件。我们站点上就曾有人在管理员页面上留言,结果等我看到已经是6个月之后了。

4个月
avatar
Reasno
0

回复@Icicle:应该在module最后加上一个return p 我例子里忘记了 已补上。还有就是根据@Honestleaf 反馈 方法二的index有些问题。建议暂时先用方法一。

4个月
avatar
Icicle
0

内置函数调用那个似乎不可用 而且最后那个是model不是mode吧

4个月
avatar
Honestleaf
0

对,那个应该是笔误。

4个月
avatar
Honestleaf
0

不错不错,需要好好研究下~

4个月
avatar
Reasno
0

来玩嘛 测试一下看看有什么bug~

4个月
avatar
Honestleaf
0

回复@Reasno:我建了一个简单的测试(用mustache重现灰机的tab),可不知为什么table里面的二级参数并没有被读取出来(我用的是mw.ext.mustache),麻烦城管有空帮我看看吧。相关页面:darksouls:Html:Tab darksouls:沙盒 darksouls:Module:Tab

4个月
avatar
Reasno
0

回复@Honestleaf:看了下。是Lua数组从1开始导致的。解决办法可以参照 http://darks…E5%9D%97:Tab 手动从0开始index。mw.ext.mustache其实和lustache的原生lua方案不一样,原理上是通过PHP来调用Mustache引擎的,lua和php index1和0不一致的问题导致了渲染失败。从php这边倒是可以强制转换成0-based array。但是不确定是否会导致其他问题。你怎么看?是否应该吧所有1开头的数组都转成0的?

4个月
avatar
Honestleaf
0

回复@Reasno:嗯,其实我之前也怀疑可能是index的问题。我记得Scribunto的mw.text.jsonEncode这个函数在转换时就针对这种情况设置了一个额外的flag参数,或许我们也可以效仿他们的做法?

4个月
avatar
Reasno
0

回复@Honestleaf:这个主意不错,加一个optional的flag看上去影响最小。

4个月
avatar
Reasno
1

回复@Honestleaf: 增加了第三个可选参数 mw.ext.mustache.REORDER_KEYS 。下个版本才会发布 暂时还是用手动[0][1][2]吧。

4个月
avatar
Honestleaf
0

回复@Reasno:好的

4个月
avatar
Reasno
0

回复@Honestleaf: 我又改成PRESERVE_KEYS了。。默认转换。

4个月
avatar
Honestleaf
0

回复@Reasno:我从0开始index后,又遇到一个问题:【0】这一项会跑到最后去。示例就在原来那个沙盒页面上。

4个月
avatar
Reasno
0

回复@Honestleaf: 没想到啊 好多问题。还是用perserve_keys吧 或者用lustache。

4个月
avatar
Honestleaf
0

回复@Reasno:哦哦,原来现在已经改了,我还以为要等到下个版本。居然还傻呵呵地手动index:sob:

4个月
avatar
Honestleaf
0

回复@Reasno:好吧,似乎并没有。我还是先手动排序,等下个版本再改。因为要用到<a>所以暂不考虑lustache。

4个月