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

Module:Category handler

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [创建] [刷新]
  1. --------------------------------------------------------------------------------
  2. -- --
  3. -- CATEGORY HANDLER --
  4. -- --
  5. -- This module implements the {{category handler}} template in Lua, --
  6. -- with a few improvements: all namespaces and all namespace aliases --
  7. -- are supported, and namespace names are detected automatically for --
  8. -- the local wiki. This module requires [[Module:Namespace detect]] --
  9. -- and [[Module:Yesno]] to be available on the local wiki. It can be --
  10. -- configured for different wikis by altering the values in --
  11. -- [[Module:Category handler/config]], and pages can be blacklisted --
  12. -- from categorisation by using [[Module:Category handler/blacklist]]. --
  13. -- --
  14. --------------------------------------------------------------------------------
  15. -- Load required modules
  16. local yesno = require('Module:Yesno')
  17. -- Lazily load things we don't always need
  18. local mShared, mappings
  19. local p = {}
  20. --------------------------------------------------------------------------------
  21. -- Helper functions
  22. --------------------------------------------------------------------------------
  23. local function trimWhitespace(s, removeBlanks)
  24. if type(s) ~= 'string' then
  25. return s
  26. end
  27. s = s:match('^%s*(.-)%s*$')
  28. if removeBlanks then
  29. if s ~= '' then
  30. return s
  31. else
  32. return nil
  33. end
  34. else
  35. return s
  36. end
  37. end
  38. --------------------------------------------------------------------------------
  39. -- CategoryHandler class
  40. --------------------------------------------------------------------------------
  41. local CategoryHandler = {}
  42. CategoryHandler.__index = CategoryHandler
  43. function CategoryHandler.new(data, args)
  44. local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
  45. -- Set the title object
  46. do
  47. local pagename = obj:parameter('demopage')
  48. local success, titleObj
  49. if pagename then
  50. success, titleObj = pcall(mw.title.new, pagename)
  51. end
  52. if success and titleObj then
  53. obj.title = titleObj
  54. if titleObj == mw.title.getCurrentTitle() then
  55. obj._usesCurrentTitle = true
  56. end
  57. else
  58. obj.title = mw.title.getCurrentTitle()
  59. obj._usesCurrentTitle = true
  60. end
  61. end
  62. -- Set suppression parameter values
  63. for _, key in ipairs{'nocat', 'categories'} do
  64. local value = obj:parameter(key)
  65. value = trimWhitespace(value, true)
  66. obj['_' .. key] = yesno(value)
  67. end
  68. do
  69. local subpage = obj:parameter('subpage')
  70. local category2 = obj:parameter('category2')
  71. if type(subpage) == 'string' then
  72. subpage = mw.ustring.lower(subpage)
  73. end
  74. if type(category2) == 'string' then
  75. subpage = mw.ustring.lower(category2)
  76. end
  77. obj._subpage = trimWhitespace(subpage, true)
  78. obj._category2 = trimWhitespace(category2) -- don't remove blank values
  79. end
  80. return obj
  81. end
  82. function CategoryHandler:parameter(key)
  83. local parameterNames = self._data.parameters[key]
  84. local pntype = type(parameterNames)
  85. if pntype == 'string' or pntype == 'number' then
  86. return self._args[parameterNames]
  87. elseif pntype == 'table' then
  88. for _, name in ipairs(parameterNames) do
  89. local value = self._args[name]
  90. if value ~= nil then
  91. return value
  92. end
  93. end
  94. return nil
  95. else
  96. error(string.format(
  97. 'invalid config key "%s"',
  98. tostring(key)
  99. ), 2)
  100. end
  101. end
  102. function CategoryHandler:isSuppressedByArguments()
  103. return
  104. -- See if a category suppression argument has been set.
  105. self._nocat == true
  106. or self._categories == false
  107. or (
  108. self._category2
  109. and self._category2 ~= self._data.category2Yes
  110. and self._category2 ~= self._data.category2Negative
  111. )
  112. -- Check whether we are on a subpage, and see if categories are
  113. -- suppressed based on our subpage status.
  114. or self._subpage == self._data.subpageNo and self.title.isSubpage
  115. or self._subpage == self._data.subpageOnly and not self.title.isSubpage
  116. end
  117. function CategoryHandler:shouldSkipBlacklistCheck()
  118. -- Check whether the category suppression arguments indicate we
  119. -- should skip the blacklist check.
  120. return self._nocat == false
  121. or self._categories == true
  122. or self._category2 == self._data.category2Yes
  123. end
  124. function CategoryHandler:matchesBlacklist()
  125. if self._usesCurrentTitle then
  126. return self._data.currentTitleMatchesBlacklist
  127. else
  128. mShared = mShared or require('Module:Category handler/shared')
  129. return mShared.matchesBlacklist(
  130. self.title.prefixedText,
  131. mw.loadData('Module:Category handler/blacklist')
  132. )
  133. end
  134. end
  135. function CategoryHandler:isSuppressed()
  136. -- Find if categories are suppressed by either the arguments or by
  137. -- matching the blacklist.
  138. return self:isSuppressedByArguments()
  139. or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
  140. end
  141. function CategoryHandler:getNamespaceParameters()
  142. if self._usesCurrentTitle then
  143. return self._data.currentTitleNamespaceParameters
  144. else
  145. if not mappings then
  146. mShared = mShared or require('Module:Category handler/shared')
  147. mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
  148. end
  149. return mShared.getNamespaceParameters(
  150. self.title,
  151. mappings
  152. )
  153. end
  154. end
  155. function CategoryHandler:namespaceParametersExist()
  156. -- Find whether any namespace parameters have been specified.
  157. -- We use the order "all" --> namespace params --> "other" as this is what
  158. -- the old template did.
  159. if self:parameter('all') then
  160. return true
  161. end
  162. if not mappings then
  163. mShared = mShared or require('Module:Category handler/shared')
  164. mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
  165. end
  166. for ns, params in pairs(mappings) do
  167. for i, param in ipairs(params) do
  168. if self._args[param] then
  169. return true
  170. end
  171. end
  172. end
  173. if self:parameter('other') then
  174. return true
  175. end
  176. return false
  177. end
  178. function CategoryHandler:getCategories()
  179. local params = self:getNamespaceParameters()
  180. local nsCategory
  181. for i, param in ipairs(params) do
  182. local value = self._args[param]
  183. if value ~= nil then
  184. nsCategory = value
  185. break
  186. end
  187. end
  188. if nsCategory ~= nil or self:namespaceParametersExist() then
  189. -- Namespace parameters exist - advanced usage.
  190. if nsCategory == nil then
  191. nsCategory = self:parameter('other')
  192. end
  193. local ret = {self:parameter('all')}
  194. local numParam = tonumber(nsCategory)
  195. if numParam and numParam >= 1 and math.floor(numParam) == numParam then
  196. -- nsCategory is an integer
  197. ret[#ret + 1] = self._args[numParam]
  198. else
  199. ret[#ret + 1] = nsCategory
  200. end
  201. if #ret < 1 then
  202. return nil
  203. else
  204. return table.concat(ret)
  205. end
  206. elseif self._data.defaultNamespaces[self.title.namespace] then
  207. -- Namespace parameters don't exist, simple usage.
  208. return self._args[1]
  209. end
  210. return nil
  211. end
  212. --------------------------------------------------------------------------------
  213. -- Exports
  214. --------------------------------------------------------------------------------
  215. local p = {}
  216. function p._exportClasses()
  217. -- Used for testing purposes.
  218. return {
  219. CategoryHandler = CategoryHandler
  220. }
  221. end
  222. function p._main(args, data)
  223. data = data or mw.loadData('Module:Category handler/data')
  224. local handler = CategoryHandler.new(data, args)
  225. if handler:isSuppressed() then
  226. return nil
  227. end
  228. return handler:getCategories()
  229. end
  230. function p.main(frame, data)
  231. data = data or mw.loadData('Module:Category handler/data')
  232. local args = require('Module:Arguments').getArgs(frame, {
  233. wrappers = data.wrappers,
  234. valueFunc = function (k, v)
  235. v = trimWhitespace(v)
  236. if type(k) == 'number' then
  237. if v ~= '' then
  238. return v
  239. else
  240. return nil
  241. end
  242. else
  243. return v
  244. end
  245. end
  246. })
  247. return p._main(args, data)
  248. end
  249. return p