Tools 是非官方社区Wiki。社区文档正在编写中,欢迎参与。 Wiki编辑答疑群:717421103
版本250722.2
全站通知:

帮助:解析函数/invoke

来自WIKI实验室WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

invoke是一个解析函数。帮助:解析函数页列出了所有解析函数的说明。

invoke

调用Lua模块。出自扩展 Scribunto

执行通过Lua编写的模块函数,提供高性能的复杂逻辑处理能力。

Lua模块,用于替代需要编写复杂嵌套解析函数的需求,提升性能和可读性。也用于充当“数据库”,如读取、检索以json格式存储的数据,便于统一的数据存储更新。


请参阅:

模块和Lua
灰机Wiki: 帮助:模块 (推荐)

语法

{{#invoke: 模块名 | 函数名 | 参数1 | 参数2 | ... }}

  • 模块名:位于模块命名空间的页面名
  • 函数名:模块中定义的Lua函数名
  • 参数(可选):传递给Lua函数的参数,可指定参数名

当模块或函数不存在,或发生运行时错误时,会生成错误信息。

示例

  • 基础调用 {{#invoke:Math|add|5|3}} → 执行Math模块的add函数
  • 带复杂参数 {{#invoke:DataProcessor|format_table|header=Yes|data={{FULLPAGENAME}}}} → 动态处理页面数据

底层代码

来自MediaWiki及其扩展的源代码,运行在服务端。此处仅供快速查阅,便于更充分的挖掘其“特性”。

/** mediawiki-extensions-Scribunto-e6f636f\includes\common\Hooks.php
 * Hook function for {{#invoke:module|func}}
 *
 * @param Parser $parser
 * @param PPFrame $frame
 * @param array $args
 * @throws MWException
 * @throws ScribuntoException
 * @return string
 */
public static function invokeHook( Parser $parser, PPFrame $frame, array $args ) {
	global $wgScribuntoGatherFunctionStats; // default: false

	try {
		if ( count( $args ) < 2 ) {
			throw new ScribuntoException( 'scribunto-common-nofunction' );
		}
		$moduleName = trim( $frame->expand( $args[0] ) );
		$engine = Scribunto::getParserEngine( $parser );

		$title = Title::makeTitleSafe( NS_MODULE, $moduleName );
		if ( !$title || !$title->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
			throw new ScribuntoException( 'scribunto-common-nosuchmodule',
				[ 'args' => [ $moduleName ] ] );
		}
		$module = $engine->fetchModuleFromParser( $title );
		if ( !$module ) {
			throw new ScribuntoException( 'scribunto-common-nosuchmodule',
				[ 'args' => [ $moduleName ] ] );
		}
		$functionName = trim( $frame->expand( $args[1] ) );

		$bits = $args[1]->splitArg();
		unset( $args[0] ); 
		unset( $args[1] );

		// If $bits['index'] is empty, then the function name was parsed as a
		// key=value pair (because of an equals sign in it), and since it didn't
		// have an index, we don't need the index offset.
		$childFrame = $frame->newChild( $args, $title, $bits['index'] === '' ? 0 : 1 );

		if ( $wgScribuntoGatherFunctionStats ) {
			$u0 = $engine->getResourceUsage( $engine::CPU_SECONDS );
			$result = $module->invoke( $functionName, $childFrame );
			$u1 = $engine->getResourceUsage( $engine::CPU_SECONDS );

			if ( $u1 > $u0 ) {
				$timingMs = (int)( 1000 * ( $u1 - $u0 ) );
				// Since the overhead of stats is worst when when #invoke
				// calls are very short, don't process measurements <= 20ms.
				if ( $timingMs > 20 ) {
					self::reportTiming( $moduleName, $functionName, $timingMs );
				}
			}
		} else {
			$result = $module->invoke( $functionName, $childFrame );
		}

		return Validator::cleanUp( strval( $result ) );
	} catch ( ScribuntoException $e ) {
		$trace = $e->getScriptTraceHtml( [ 'msgOptions' => [ 'content' ] ] );
		$html = Html::element( 'p', [], $e->getMessage() );
		if ( $trace !== false ) {
			$html .= Html::element( 'p',
				[],
				wfMessage( 'scribunto-common-backtrace' )->inContentLanguage()->text()
			) . $trace;
		} else {
			$html .= Html::element( 'p',
				[],
				wfMessage( 'scribunto-common-no-details' )->inContentLanguage()->text()
			);
		}
		$out = $parser->getOutput();
		$errors = $out->getExtensionData( 'ScribuntoErrors' );
		if ( $errors === null ) {
			// On first hook use, set up error array and output
			$errors = [];
			$parser->addTrackingCategory( 'scribunto-common-error-category' );
			$out->addModules( 'ext.scribunto.errors' );
		}
		$errors[] = $html;
		$out->setExtensionData( 'ScribuntoErrors', $errors );
		$out->addJsConfigVars( 'ScribuntoErrors', $errors );
		$id = 'mw-scribunto-error-' . ( count( $errors ) - 1 );
		$parserError = htmlspecialchars( $e->getMessage() );

		// #iferror-compatible error element
		return "<strong class=\"error\"><span class=\"scribunto-error\" id=\"$id\">" .
			$parserError . "</span></strong>";
	}
}
代码逻辑:
  • 强制要求至少提供模块名和函数名两个参数
  • 自动加载模块内容并验证有效性(不存在模块或非Lua模块会报错)
  • 创建独立执行环境运行Lua函数,支持参数透传
  • 错误处理机制会捕获Lua异常并生成带追踪ID的HTML错误元素

实际用例

一些Wiki使用了相关特性,如下所示这个静态列表可能在下列页面更改后过时仅供批判性参考
碧蓝航线 - blhx

原神 - ys

战双帕弥什 - zspms

恋与深空 - lysk

代号鸢 - yuan

赛马娘 - umamusume

尘白禁区 - sonw

WIKI实验室 - tools

卡拉彼丘 - klbq

白荆回廊 - bjhl

女神转生 - persona

赛尔计划 - seerplan

雷索纳斯 - resonance

重返未来:1999 - reverse1999

偶像大师灰姑娘女孩 - imascg

公主连结 - pcr

ミナシゴノシゴト - mnsg

奇迹暖暖 - qjnn

地下城堡3 - dxcb3

交错战线 - crosscore

千年之旅 - elf

戴森球计划 - dsp

StardewValley星露谷物语 - stardewvalley

赛尔号星球大战 - seerwar

方舟指令 - fzzl

少前2:追放 - gf2

偶像荣耀/idoly pride - idolypride

深空之眼 - dhmmr

克鲁赛德战记 - cq

烟雨江湖 - yanyu

灰烬战线 - hjzx