置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Example

猛汉♂百科,万男皆可猛的百科全书!转载请标注来源页面的网页链接,并声明引自猛汉百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [创建] [刷新]
  1. local module = {}
  2. local insert = table.insert
  3. local concat = table.concat
  4. local getArgs = require('Module:Arguments').getArgs
  5. local NOWIKI_STRIP_MARKER_PATTERN = '\127\'"`UNIQ%-%-nowiki%-%x%x%x%x%x%x%x%x%-QINU`"\'\127'
  6. local function _main(args, frame)
  7. local codes = args[1]
  8. local isPrint = args[2] == 'print'
  9. local preTag = frame:extensionTag('pre', codes)
  10. local executedResult = frame:preprocess(
  11. mw.text.decode(
  12. mw.text.unstripNoWiki(codes)
  13. )
  14. )
  15. if isPrint then
  16. return preTag..mw.text.trim(executedResult)
  17. else
  18. frame:callParserFunction('#vardefine', 'example-view', executedResult)
  19. return preTag
  20. end
  21. end
  22. local unstripNoWiki = mw.text.unstripNoWiki
  23. local entityToChar = {['&lt;'] = '<', ['&gt;'] = '>'}
  24. local charToEntity = {
  25. ['<'] = '&lt;',
  26. ['>'] = '&gt;',
  27. ['&'] = '&amp;',
  28. [':'] = '&#58;', -- 防止自动超链接
  29. ['['] = '&#91;',
  30. [']'] = '&#93;',
  31. ['{'] = '&#123;',
  32. ['|'] = '&#124;',
  33. ['}'] = '&#125;',
  34. }
  35. --- 从文本中提取出用于显示的代码(经过转义)和用于执行的代码
  36. local function extractCodeForDisplayAndForExec(text)
  37. local codeForDisplay = {}
  38. local codeForExec = {}
  39. local function appendWikitext(normalText)
  40. codeForDisplay[#codeForDisplay + 1] = normalText
  41. end
  42. local function appendNowiki(nowikiStripMarker)
  43. -- 妈的mw.text.unstripNoWiki(<nowiki>< > &lt; &gt;</nowiki>)会得到'&lt; &gt; &lt; &gt;',
  44. -- 这导致<nowiki>< ></nowiki>与<nowiki>&lt; &gt;</nowiki>之间的区别丢失了。
  45. -- 因此,我们只能择其一:
  46. -- - 将unstripNoWiki得到的所有'&lt;'和'&gt;'替换为'<'和'>',在调用模板时以其他方式表达'&lt;'和'&gt;'
  47. -- - 不转换unstripNoWiki得到的'&lt;'和'&gt;',在调用模板时以其他方式表达'<'和'>'
  48. -- 考虑到'<'、'>'的使用频率更高,此模块选择了前者。
  49. local encodedSrcCode
  50. local srcCode = unstripNoWiki(nowikiStripMarker):gsub('&[lg]t;', entityToChar)
  51. do
  52. -- <_nowiki>和</_nowiki>转换为<nowiki>和</nowiki>
  53. -- <__nowiki>和</__nowiki>转换为<_nowiki>和</_nowiki>
  54. -- 以此类推
  55. local matchTimes = 0
  56. srcCode, matchTimes =
  57. srcCode:gsub('<(/?_-)_([nN][oO][wW][iI][kK][iI]%s*)>', '<%1%2>')
  58. if matchTimes > 0 then
  59. encodedSrcCode = srcCode
  60. end
  61. end
  62. if encodedSrcCode or srcCode:find('[<>&]') then
  63. encodedSrcCode = (encodedSrcCode or srcCode):gsub('[<>&:%[%]{|}]', charToEntity)
  64. end
  65. codeForDisplay[#codeForDisplay + 1] = encodedSrcCode or nowikiStripMarker
  66. codeForExec[#codeForExec + 1] = srcCode
  67. end
  68. local last = 1
  69. local nowikiStart, nowikiEnd = text:find(NOWIKI_STRIP_MARKER_PATTERN)
  70. local beginsWithNowiki = nowikiStart == 1 -- 这个值用来稍后去除多余换行
  71. while nowikiStart do
  72. if nowikiStart > last then
  73. -- 补上<nowiki>之前的部分
  74. appendWikitext(text:sub(last, nowikiStart - 1))
  75. end
  76. appendNowiki(text:sub(nowikiStart, nowikiEnd))
  77. last = nowikiEnd + 1
  78. nowikiStart, nowikiEnd = text:find(NOWIKI_STRIP_MARKER_PATTERN, last)
  79. end
  80. if last <= #text then
  81. appendWikitext(text:sub(last))
  82. else
  83. local len = #codeForExec
  84. codeForExec[len] = codeForExec[len]:gsub('\n$', '', 1)
  85. end
  86. -- 删除多余换行
  87. if beginsWithNowiki then
  88. codeForExec[1] = codeForExec[1]:gsub('^\n', '', 1)
  89. end
  90. return concat(codeForDisplay), concat(codeForExec)
  91. end
  92. local function canary(args, frame)
  93. local tag, code, seperator
  94. if args.pre then
  95. tag = 'pre'
  96. code = args.pre
  97. seperator = '\n'..(args[1] or '')
  98. elseif args.code then
  99. tag = 'code'
  100. code = args.code
  101. seperator = args[1] or ''
  102. elseif args.bare then
  103. tag = nil
  104. code = args.bare
  105. seperator = args[1] or ''
  106. elseif args[1] then
  107. tag = 'pre'
  108. code = args[1]
  109. seperator = '\n'..(args[2] or '')
  110. else
  111. return '<strong class="error">{{[[Template:Example|Example]]}}调用错误</strong>'
  112. end
  113. assert(code)
  114. assert(seperator)
  115. local codeForDisplay, codeForExec = extractCodeForDisplayAndForExec(code)
  116. local result = tag and {'<', tag, '>', codeForDisplay, '</', tag, '>'} or {codeForDisplay}
  117. if args.echo == '' then
  118. return concat(result)
  119. end
  120. result[#result + 1] = seperator
  121. result[#result + 1] = frame:preprocess(codeForExec)
  122. return concat(result)
  123. end
  124. function module.main(frame)
  125. local parent = frame:getParent()
  126. if parent and parent:getTitle() == 'Template:Example' then
  127. -- frame = parent
  128. else
  129. parent = nil
  130. -- 为了兼容旧函数才这样写
  131. -- canary状态结束后改掉
  132. end
  133. local args = (parent or frame).args
  134. if args.pre or args.code or args.bare then
  135. return canary(args, parent or frame)
  136. end
  137. return _main(getArgs(frame), frame)
  138. end
  139. return module