Module:Example
跳到导航
跳到搜索
- local module = {}
- local insert = table.insert
- local concat = table.concat
- local getArgs = require('Module:Arguments').getArgs
- local NOWIKI_STRIP_MARKER_PATTERN = '\127\'"`UNIQ%-%-nowiki%-%x%x%x%x%x%x%x%x%-QINU`"\'\127'
- local function _main(args, frame)
- local codes = args[1]
- local isPrint = args[2] == 'print'
- local preTag = frame:extensionTag('pre', codes)
- local executedResult = frame:preprocess(
- mw.text.decode(
- mw.text.unstripNoWiki(codes)
- )
- )
- if isPrint then
- return preTag..mw.text.trim(executedResult)
- else
- frame:callParserFunction('#vardefine', 'example-view', executedResult)
- return preTag
- end
- end
- local unstripNoWiki = mw.text.unstripNoWiki
- local entityToChar = {['<'] = '<', ['>'] = '>'}
- local charToEntity = {
- ['<'] = '<',
- ['>'] = '>',
- ['&'] = '&',
- [':'] = ':', -- 防止自动超链接
- ['['] = '[',
- [']'] = ']',
- ['{'] = '{',
- ['|'] = '|',
- ['}'] = '}',
- }
- --- 从文本中提取出用于显示的代码(经过转义)和用于执行的代码
- local function extractCodeForDisplayAndForExec(text)
- local codeForDisplay = {}
- local codeForExec = {}
- local function appendWikitext(normalText)
- codeForDisplay[#codeForDisplay + 1] = normalText
- end
- local function appendNowiki(nowikiStripMarker)
- -- 妈的mw.text.unstripNoWiki(<nowiki>< > < ></nowiki>)会得到'< > < >',
- -- 这导致<nowiki>< ></nowiki>与<nowiki>< ></nowiki>之间的区别丢失了。
- -- 因此,我们只能择其一:
- -- - 将unstripNoWiki得到的所有'<'和'>'替换为'<'和'>',在调用模板时以其他方式表达'<'和'>'
- -- - 不转换unstripNoWiki得到的'<'和'>',在调用模板时以其他方式表达'<'和'>'
- -- 考虑到'<'、'>'的使用频率更高,此模块选择了前者。
- local encodedSrcCode
- local srcCode = unstripNoWiki(nowikiStripMarker):gsub('&[lg]t;', entityToChar)
- do
- -- <_nowiki>和</_nowiki>转换为<nowiki>和</nowiki>
- -- <__nowiki>和</__nowiki>转换为<_nowiki>和</_nowiki>
- -- 以此类推
- local matchTimes = 0
- srcCode, matchTimes =
- srcCode:gsub('<(/?_-)_([nN][oO][wW][iI][kK][iI]%s*)>', '<%1%2>')
- if matchTimes > 0 then
- encodedSrcCode = srcCode
- end
- end
- if encodedSrcCode or srcCode:find('[<>&]') then
- encodedSrcCode = (encodedSrcCode or srcCode):gsub('[<>&:%[%]{|}]', charToEntity)
- end
- codeForDisplay[#codeForDisplay + 1] = encodedSrcCode or nowikiStripMarker
- codeForExec[#codeForExec + 1] = srcCode
- end
- local last = 1
- local nowikiStart, nowikiEnd = text:find(NOWIKI_STRIP_MARKER_PATTERN)
- local beginsWithNowiki = nowikiStart == 1 -- 这个值用来稍后去除多余换行
- while nowikiStart do
- if nowikiStart > last then
- -- 补上<nowiki>之前的部分
- appendWikitext(text:sub(last, nowikiStart - 1))
- end
- appendNowiki(text:sub(nowikiStart, nowikiEnd))
- last = nowikiEnd + 1
- nowikiStart, nowikiEnd = text:find(NOWIKI_STRIP_MARKER_PATTERN, last)
- end
- if last <= #text then
- appendWikitext(text:sub(last))
- else
- local len = #codeForExec
- codeForExec[len] = codeForExec[len]:gsub('\n$', '', 1)
- end
- -- 删除多余换行
- if beginsWithNowiki then
- codeForExec[1] = codeForExec[1]:gsub('^\n', '', 1)
- end
- return concat(codeForDisplay), concat(codeForExec)
- end
- local function canary(args, frame)
- local tag, code, seperator
- if args.pre then
- tag = 'pre'
- code = args.pre
- seperator = '\n'..(args[1] or '')
- elseif args.code then
- tag = 'code'
- code = args.code
- seperator = args[1] or ''
- elseif args.bare then
- tag = nil
- code = args.bare
- seperator = args[1] or ''
- elseif args[1] then
- tag = 'pre'
- code = args[1]
- seperator = '\n'..(args[2] or '')
- else
- return '<strong class="error">{{[[Template:Example|Example]]}}调用错误</strong>'
- end
- assert(code)
- assert(seperator)
- local codeForDisplay, codeForExec = extractCodeForDisplayAndForExec(code)
- local result = tag and {'<', tag, '>', codeForDisplay, '</', tag, '>'} or {codeForDisplay}
- if args.echo == '' then
- return concat(result)
- end
- result[#result + 1] = seperator
- result[#result + 1] = frame:preprocess(codeForExec)
- return concat(result)
- end
- function module.main(frame)
- local parent = frame:getParent()
- if parent and parent:getTitle() == 'Template:Example' then
- -- frame = parent
- else
- parent = nil
- -- 为了兼容旧函数才这样写
- -- canary状态结束后改掉
- end
- local args = (parent or frame).args
- if args.pre or args.code or args.bare then
- return canary(args, parent or frame)
- end
- return _main(getArgs(frame), frame)
- end
- return module