模块:Documentation

求闻百科,共笔求闻

本模板生成一个包含模板模块或其他页面的文档绿框。通常运行于模板链接:{{documentation}}模板中。

常规用法

多数情况下,这个模块用模板链接:{{documentation}}模板调用。请参阅模板页的介绍及参数。

用在其他模块

为在其他Lua模块使用,先通过require载入:

local documentation = require('Module:Documentation')._main

然后您可以简单地用一组参数调用。

documentation{content = 'Some documentation'}

请参阅模板页的使用说明及参数。

上述文档内容嵌入自Module:Documentation/doc编辑 | 历史
编者可以在本模块的沙盒编辑和测试样例创建页面进行实验。
请将模块自身所属的分类添加在文档中。本模块的子页面
-- 本模块是从维基百科的相关模块简化的。

local p = {}
local getArgs = require 'Module:Arguments'.getArgs
require 'Module:No globals'

function p._main(args, f)
  -- args是不含元表的表
  -- f是框架,应该作为第二个参数传入
  f = f or mw.getCurrentFrame()
  args = args or {}
  
  local content = args.content
  -- 关于标题对象的处理
  local title=args.page and mw.title.new(args.page)
              or mw.title.getCurrentTitle()
  local T=tostring(title)
  
  local doctitle=args[1] and mw.title.new(args[1])
               or mw.title.new(T.."/doc")
  local D=tostring(doctitle)
  local sandboxtitle=mw.title.new(T.."/sandbox")
  local S=tostring(sandboxtitle)
  local testcasestitle=mw.title.new(T.."/testcases")
  local E=tostring(testcasestitle)
  local document, doc_exists
  local fullurl = require '模块:fullurl'._fullurl
  local pageName = require '模块:page name'.pageName(T)
  local env = p.getEnvironment(args)
  
  if content then
    document = content
  else
    --先获取文档内容
    local doc_exists = doctitle.exists
    local state -- boolean
    if not doc_exists then
      document=('本%s还没有文档页面。')
          :format(pageName)
    else
      state, document = pcall(function() 
        return f:expandTemplate{title=doctitle,args={isdoc=1}} 
      end)
      if not state then
        document='尝试调用文档内容时发生未知错误:'..document
      end
    end
  end
  
  local autogen = {}
  if title and title.namespace==828 then
    do
  		-- 尝试获取页面内容并识别重定向。
  		local successes, page_content = pcall(title.getContent, title)
  		if successes then
  			local target = nil  -- 模块可能重定向至的页面名称。
  			local match = page_content:match '%s*return%s+require%s*(.+)%;*%s*'
  			if match then
  				match = match:match '^%s*%((.-)%)%s*$' or match
  				target = match:match '^%s*"(.-)"%s*$' or match:match "^%s*'(.-)'%s*$"
  					or match:match "^%s*%[%[(.-)%]%]%s$"
  			end
  			if target then
  				autogen[#autogen + 1] = "本模块是一个重定向模块,重定向至[[" .. target .. "]]。"
  			end
  		else
  			mw.log("[Module:Documentation] 尝试获取页面内容时出现错误:" .. page_content)
  		end
  	end
    if title.isSubpage and title.rootText == 'CGroup' then
      local CGroupViewer = require('Module:CGroupViewer')
    	autogen[#autogen + 1] = [=[
<hr>

以下内容根据模块内容通过[[Module:CGroupViewer]]模块生成,仅供参考。

]=] .. CGroupViewer.main(f:newChild({args = {title.subpageText}}))
    end
  end
  
  local contents = {
    photo="[[File:Information Mark (Blue).svg |24px|link=|alt=文档图示]] '''"..pageName --不同名字空间显示不同名字
          .."-{zh-hans:文档;zh-hant:文件}-'''",
    edit=string.format("&#91;[[Special:EditPage/%s|编辑]]&#93;",D), -- 编辑按钮
    hist=string.format("&#91;[[Special:PageHistory/%s|查看历史]]&#93;",D), -- 查看历史按钮
    purge=string.format("&#91;[[Special:Purge/%s|清除-{zh-hans:缓存;zh-hant:快取}-]]&#93;",T), -- 清除缓存按钮
    goto_code = '&#91;[[#to-code|跳转到代码]]&#93;',
    set=string.format('您可以%s文档以让用户更好地理解本%s的用途。', fullurl{title=D,action='edit',text='创建',redlink='1'}, pageName),
    context=('上述文档内容由%s本身直接提供,请查看页面源代码。'):format(pageName),
    invtext=string.format('编者可以在本%s的沙盒<small>(%s)</small>和测试样例<small>(%s)</small>页面进行实验。<br>',pageName,
          sandboxtitle.exists and string.format("[[Special:EditPage/%s|编辑]]",S) or fullurl{title=S,action='edit',redlink='1',text='创建'} .. ' &#124; ' .. fullurl{title=S,action='edit',preload=T,text='镜像'}, --“沙盒”后括号内的文字
          testcasestitle.exists and string.format("[[Special:EditPage/%s|编辑]]",E) or fullurl{title=E,action='edit',redlink='1',text='创建'}
        )
  }
  
  local root=mw.html.create()
		:wikitext(p._getModuleWikitext(args, env))

  local css = {['clear']= 'both';
	    ['border']= '1px solid #a2a9b1'; 
	    ['background-color']= '#ecfcf4'; 
	    ['padding']= '5px';
  }
  local editsectionlike = content and 
            {contents.purge}
            or doctitle.exists and
            {
            string.format("&#91;[[%s|-{zh-cn:查看;zh-tw:檢視}-]]&#93;",D), -- 查看按钮
            contents.edit,
            contents.hist,
            contents.purge
            }
            or {
            string.format("&#91;%s]", 
            fullurl{title=D,action='edit',redlink='1',text='创建'}
            )}
  if title.namespace == 828 then
    editsectionlike[#editsectionlike + 1] = contents.goto_code end
  root
    :tag'div'
      :addClass'template-documentation iezoomfix'
      :css('margin', '1em 0')
      :newline()
      :tag"div"
        :addClass 'template-documentation-header'
        :css('margin-bottom', '0.2em')
        :css(css)
        :tag"span" --“模板文档”以及前的图片
          :css{
            ['font-size']='110%',
          }
          :wikitext(contents.photo)
        :done()
        :tag"span" --其后的编辑等按钮
          :addClass"mw-editsection-like"
          :wikitext(table.concat(editsectionlike, ' ')) -- “:wikitext”的参数结束
        :done()
      :done()
      :newline()
      :tag 'div'
        :addClass 'template-documentation-body mw-parser-output'
        :css(css)
        :wikitext(string.sub(document,1,1)~='\n' and '\n' or nil)
        :wikitext(document)
        :wikitext(table.concat(autogen)) -- 自动生成的部分,可能为nil
        :wikitext(string.sub(document,-1,-1)~='\n' and '\n' or nil)
        :tag 'div'
          :css('clear', 'both')
          :done()
      :done()
      :tag"div"
        :addClass"template-documentation-foot"
        :css(css)
        :css{
        	padding = '0.25em 0.9em';
			['margin-top'] = '0.2em';
		}
        :wikitext(
          content and contents.context
          or doctitle.exists and string.format(
            '上述文档内容嵌入自[[%s]]。<small style="font-style:normal">([[Special:EditPage/%s|编辑]] &#124; [[Special:PageHistory/%s|历史]])</small>',
          D,
          D,
          D)
          or contents.set
        )
        :wikitext(#autogen > 0 and '部分内容为自动生成。' or nil)
        :wikitext '<br>'
        :wikitext(contents.invtext)
        :wikitext(('请将%s自身所属的分类添加在文档中。[[Special:前缀索引/%s/|本%s的子页面]]。'):format(pageName, T, pageName))
  if title.namespace == 828 then
    root:tag 'div'
        :attr('id', 'to-code') end
  return tostring(root)
end


----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------

function p.getEnvironment(args)
	--[[
	-- Returns a table with information about the environment, including title objects and other namespace- or
	-- path-related data.
	-- @args - table of arguments passed by the user
	--
	-- Title objects include:
	-- env.title - the page we are making documentation for (usually the current title)
	-- env.templateTitle - the template (or module, file, etc.)
	-- env.docTitle - the /doc subpage.
	-- env.sandboxTitle - the /sandbox subpage.
	-- env.testcasesTitle - the /testcases subpage.
	-- env.printTitle - the print version of the template, located at the /Print subpage.
	--
	-- Data includes:
	-- env.protectionLevels - the protection levels table of the title object.
	-- env.subjectSpace - the number of the title's subject namespace.
	-- env.docSpace - the number of the namespace the title puts its documentation in.
	-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
	-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
	-- 
	-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
	-- returned will be nil.
	--]]
	
	local env, envFuncs = {}, {}

	-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
	-- returned by that function is memoized in the env table so that we don't call any of the functions
	-- more than once. (Nils won't be memoized.)
	setmetatable(env, {
		__index = function (t, key)
			local envFunc = envFuncs[key]
			if envFunc then
				local success, val = pcall(envFunc)
				if success then
					env[key] = val -- Memoise the value.
					return val
				end
			end
			return nil
		end
	})	

	function envFuncs.title()
		-- The title object for the current page, or a test page passed with args.page.
		local title
		local titleArg = args.page
		if titleArg then
			title = mw.title.new(titleArg)
		else
			title = mw.title.getCurrentTitle()
		end
		return title
	end

	function envFuncs.templateTitle()
		--[[
		-- The template (or module, etc.) title object.
		-- Messages:
		-- 'sandbox-subpage' --> 'sandbox'
		-- 'testcases-subpage' --> 'testcases'
		--]]
		local subjectSpace = env.subjectSpace
		local title = env.title
		local subpage = title.subpageText
		if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
			return mw.title.makeTitle(subjectSpace, title.baseText)
		else
			return mw.title.makeTitle(subjectSpace, title.text)
		end
	end

	function envFuncs.docTitle()
		--[[
		-- Title object of the /doc subpage.
		-- Messages:
		-- 'doc-subpage' --> 'doc'
		--]]
		local title = env.title
		local docname = args[1] -- User-specified doc page.
		local docpage
		if docname then
			docpage = docname
		else
			docpage = env.docpageBase .. '/' .. message('doc-subpage')
		end
		return mw.title.new(docpage)
	end
	
	function envFuncs.sandboxTitle()
		--[[
		-- Title object for the /sandbox subpage.
		-- Messages:
		-- 'sandbox-subpage' --> 'sandbox'
		--]]
		return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
	end
	
	function envFuncs.testcasesTitle()
		--[[
		-- Title object for the /testcases subpage.
		-- Messages:
		-- 'testcases-subpage' --> 'testcases'
		--]]
		return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
	end
	
	function envFuncs.printTitle()
		--[[
		-- Title object for the /Print subpage.
		-- Messages:
		-- 'print-subpage' --> 'Print'
		--]]
		return env.templateTitle:subPageTitle(message('print-subpage'))
	end

	function envFuncs.protectionLevels()
		-- The protection levels table of the title object.
		return env.title.protectionLevels
	end

	function envFuncs.subjectSpace()
		-- The subject namespace number.
		return mw.site.namespaces[env.title.namespace].subject.id
	end

	function envFuncs.docSpace()
		-- The documentation namespace number. For most namespaces this is the same as the
		-- subject namespace. However, pages in the Article, File, MediaWiki or Category
		-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
		local subjectSpace = env.subjectSpace
		if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
			return subjectSpace + 1
		else
			return subjectSpace
		end
	end

	function envFuncs.docpageBase()
		-- The base page of the /doc, /sandbox, and /testcases subpages.
		-- For some namespaces this is the talk page, rather than the template page.
		local templateTitle = env.templateTitle
		local docSpace = env.docSpace
		local docSpaceText = mw.site.namespaces[docSpace].name
		-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
		return docSpaceText .. ':' .. templateTitle.text
	end
	
	function envFuncs.compareUrl()
		-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
		local templateTitle = env.templateTitle
		local sandboxTitle = env.sandboxTitle
		if templateTitle.exists and sandboxTitle.exists then
			local compareUrl = mw.uri.fullUrl(
				'Special:ComparePages',
				{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
			)
			return tostring(compareUrl)
		else
			return nil
		end
	end		

	return env
end	

----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame, {
			valueFunc = function (key, value)
				if type(value) == 'string' then
					value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
					if key == 'heading' or value ~= '' then
						return value
					else
						return nil
					end
				else
					return value
				end
			end
		})
		return p[funcName](args)
	end
end

----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')

function p._getModuleWikitext(args, env)
	local currentTitle = mw.title.getCurrentTitle()
	if currentTitle.contentModel ~= 'Scribunto' then return end
	pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
	local moduleWikitext =  package.loaded["Module:Module wikitext"]
	if moduleWikitext then
		return moduleWikitext.main()
	end
	return ''
end

----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------

function p.nonexistent(frame)
	if mw.title.getCurrentTitle().subpageText == 'testcases' then
		return frame:expandTemplate{title = 'module test cases notice'}
	else
		return p.main(frame)
	end
end

function p.main(frame)
  local args=getArgs(frame)
  return p._main(args, frame)
end

return p