灰机版本 > 2.1.0

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

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

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

在灰机上,Mustache可以和MongoDB配合使用。

使用wikitext调用

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

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

调用

自2.2.1起,原有的dot写法已经被json取代。

示例:

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

注意:在使用inline样式编写代码时,应避免结尾处出现}}},因为这会导致代码无法被正常解析。下面这段代码就会造成解析异常。

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

正确的写法是使用空格换行来将}}}分隔开,例如:

{{#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>。

案例

可参阅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>

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

Mustache官方说明文档

https://mustache.github.io/mustache.5.html

avatar
avatar
Honestleaf
0
@Reasno 又遇到一个问题:通过本页上提供的方法使用js加载mustache时似乎无法生成模板中<script>标签的内容。

另外,我在把代码放进common.js后使用调试功能时会得到“Unknown compiler mustache”的错误,只有用开发者工具之类的东西手动运行时才不会弹错(但是<script>还是没有)。感觉应该是common.js运行的时候这个compiler还没有加载?
10个月
avatar
Honestleaf
0

@Reasno 还有个问题:通过action=raw获取的html命名空间下的页面内容会受到缓存影响,而且无法通过action=purge或者保存页面刷新,有没有其他刷新缓存的办法?(我有个页面上现在还是两天前的内容)

10个月
avatar
Reasno
0

回复@Honestleaf:这个不是mw层面的缓存,可加&rand=12345 来解决

10个月
avatar
Honestleaf
0

@Reasno 发现一个问题<script>里面的&会被自动替换成&

10个月
avatar
Honestleaf
1

& amp ;

10个月
avatar
Reasno
0

回复@Honestleaf: MediaWiki 限制。 建议还是用Gadget去写js,异步执行效率好。

10个月
avatar
Honestleaf
0

回复@Reasno: 嗯,用<script>主要也是为了调试。话说,在Common.js里用ResourceLoader加载js和用Gadget加载js哪个更好?

10个月
avatar
Reasno
0

回复@Honestleaf:一样

10个月
avatar
Reasno
0

这个问题被我hack了一下 解决了

10个月
avatar
Honestleaf
0

回复@Reasno:城管威武:clap:

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

标签

1年
avatar
Reasno
0

fixed in 2.0.27

1年
avatar
Icicle
0

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

1年
avatar
Honestleaf
0

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

1年
avatar
Icicle
0

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

1年
avatar
Honestleaf
0

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

1年
avatar
Reasno
0

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

1年
avatar
Icicle
0

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

1年
avatar
Honestleaf
0

对,那个应该是笔误。

1年
avatar
Honestleaf
0

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

1年
avatar
Reasno
0

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

1年
avatar
Honestleaf
0

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

1年
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的?

1年
avatar
Honestleaf
0

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

1年
avatar
Reasno
0

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

1年
avatar
Reasno
1

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

1年
avatar
Honestleaf
0

回复@Reasno:好的

1年
avatar
Reasno
0

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

1年
avatar
Honestleaf
0

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

1年
avatar
Reasno
0

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

1年
avatar
Honestleaf
0

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

1年
avatar
Honestleaf
0

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

1年