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

Module:Multiple image

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [创建] [刷新]
  1. -- implements [[template:multiple image]]
  2. local p = {}
  3. local autoscaledimages
  4. local nonautoscaledimages
  5. local function isnotempty(s)
  6. return s and s:match( '^%s*(.-)%s*$' ) ~= ''
  7. end
  8. local function removepx(s)
  9. return tostring(s or ''):match('^(.*)[Pp][Xx]%s*$') or s
  10. end
  11. local function getdimensions(s, w, h)
  12. if tonumber(w) and tonumber(h) then
  13. nonautoscaledimages = true
  14. return tonumber(w), tonumber(h)
  15. end
  16. local file = s and mw.title.new('File:' .. mw.uri.decode(mw.ustring.gsub(s,'%|.*$',''), 'WIKI'))
  17. file = file and file.file or {width = 0, height = 0}
  18. w = tonumber(file.width) or 0
  19. h = tonumber(file.height) or 0
  20. autoscaledimages = true
  21. return w, h
  22. end
  23. local function renderImageCell(image, width, height, link, alt, thumbtime, caption, textalign, istyle)
  24. local root = mw.html.create('')
  25. local altstr = '|alt=' .. (alt or '')
  26. local linkstr = link and ('|link=' .. link) or ''
  27. local widthstr = '|' .. tostring(width) .. 'px'
  28. local thumbtimestr = ''
  29. if isnotempty( thumbtime ) then
  30. thumbtimestr = '|thumbtime=' .. thumbtime
  31. end
  32. local imagediv = root:tag('div')
  33. imagediv:addClass('thumbimage')
  34. imagediv:cssText(istyle)
  35. if( height ) then
  36. imagediv:css('height', tostring(height) .. 'px')
  37. imagediv:css('overflow', 'hidden')
  38. end
  39. imagediv:wikitext('[[file:' .. image .. widthstr .. linkstr .. altstr .. thumbtimestr .. ']]')
  40. if isnotempty(caption) then
  41. local captiondiv = root:tag('div')
  42. captiondiv:addClass('thumbcaption')
  43. if isnotempty(textalign) then
  44. captiondiv:addClass('text-align-' .. textalign)
  45. end
  46. captiondiv:wikitext(caption)
  47. end
  48. return tostring(root)
  49. end
  50. local function getWidth(w1, w2)
  51. local w
  52. if isnotempty(w1) then
  53. w = tonumber(w1)
  54. elseif isnotempty(w2) then
  55. w = tonumber(w2)
  56. end
  57. return w or 200
  58. end
  59. local function getPerRow(pstr, ic)
  60. -- split string into array using any non-digit as a dilimiter
  61. local pr = mw.text.split(pstr or '', '[^%d][^%d]*')
  62. -- if split failed, assume a single row
  63. if (#pr < 1) then
  64. pr = {tostring(ic)}
  65. end
  66. -- convert the array of strings to an array of numbers,
  67. -- adding any implied/missing numbers at the end of the array
  68. local r = 1
  69. local thisrow = tonumber(pr[1] or ic) or ic
  70. local prownum = {}
  71. while( ic > 0 ) do
  72. prownum[r] = thisrow
  73. ic = ic - thisrow
  74. r = r + 1
  75. -- use the previous if the next is missing and
  76. -- make sure we don't overstep the number of images
  77. thisrow = math.min(tonumber(pr[r] or thisrow) or ic, ic)
  78. end
  79. return prownum
  80. end
  81. local function renderMultipleImages(frame)
  82. local pargs = frame:getParent().args
  83. local args = frame.args
  84. local width = removepx(pargs['width'] or '')
  85. local dir = pargs['direction'] or ''
  86. local border = pargs['border'] or args['border'] or ''
  87. local align = pargs['align'] or args['align'] or (border == 'infobox' and 'center' or '')
  88. local capalign = pargs['caption_align'] or args['caption_align'] or ''
  89. local totalwidth = removepx(pargs['total_width'] or args['total_width'] or '')
  90. local imgstyle = pargs['image_style'] or args['image_style']
  91. local header = pargs['header'] or pargs['title'] or ''
  92. local footer = pargs['footer'] or ''
  93. local imagegap = tonumber(pargs['image_gap'] or '1') or 1
  94. local perrow = nil
  95. local thumbclass = {
  96. ["left"] = 'tleft',
  97. ["none"] = 'tnone',
  98. ["center"] = 'tnone',
  99. ["centre"] = 'tnone',
  100. ["right"] = 'tright'
  101. }
  102. -- find all the nonempty images
  103. local imagenumbers = {}
  104. local imagecount = 0
  105. for k, v in pairs( pargs ) do
  106. local i = tonumber(tostring(k):match( '^%s*image([%d]+)%s*$' ) or '0')
  107. if( i > 0 and isnotempty(v) ) then
  108. table.insert( imagenumbers, i)
  109. imagecount = imagecount + 1
  110. end
  111. end
  112. -- sort the imagenumbers
  113. table.sort(imagenumbers)
  114. -- create an array with the number of images per row
  115. perrow = getPerRow(dir == 'vertical' and '1' or pargs['perrow'], imagecount)
  116. -- compute the number of rows
  117. local rowcount = #perrow
  118. -- store the image widths and compute row widths and maximum row width
  119. local heights = {}
  120. local widths = {}
  121. local widthmax = 0
  122. local widthsum = {}
  123. local k = 0
  124. for r=1,rowcount do
  125. widthsum[r] = 0
  126. for c=1,perrow[r] do
  127. k = k + 1
  128. if( k <= imagecount ) then
  129. local i = imagenumbers[k]
  130. if( isnotempty(totalwidth) ) then
  131. widths[k], heights[k] = getdimensions(pargs['image' .. i], pargs['width' .. i], pargs['height' .. i])
  132. else
  133. widths[k] = getWidth(width, pargs['width' .. i])
  134. end
  135. widthsum[r] = widthsum[r] + widths[k]
  136. end
  137. end
  138. widthmax = math.max(widthmax, widthsum[r])
  139. end
  140. -- make sure the gap is non-negative
  141. if imagegap < 0 then imagegap = 0 end
  142. -- if total_width has been specified, rescale the image widths
  143. if( isnotempty(totalwidth) ) then
  144. totalwidth = tonumber(totalwidth)
  145. widthmax = 0
  146. local k = 0
  147. for r=1,rowcount do
  148. local koffset = k
  149. local tw = totalwidth - (3 + imagegap) * (perrow[r] - 1) - 12
  150. local ar = {}
  151. local arsum = 0
  152. for j=1,perrow[r] do
  153. k = k + 1
  154. if( k<= imagecount ) then
  155. local i = imagenumbers[k]
  156. local h = heights[k] or 0
  157. if (h > 0) then
  158. ar[j] = widths[k]/h
  159. heights[k] = h
  160. else
  161. ar[j] = widths[k]/100
  162. end
  163. arsum = arsum + ar[j]
  164. end
  165. end
  166. local ht = tw/arsum
  167. local ws = 0
  168. k = koffset
  169. for j=1,perrow[r] do
  170. k = k + 1
  171. if( k<= imagecount ) then
  172. local i = imagenumbers[k]
  173. widths[k] = math.floor(ar[j]*ht + 0.5)
  174. ws = ws + widths[k]
  175. if heights[k] then
  176. heights[k] = math.floor(ht)
  177. end
  178. end
  179. end
  180. widthsum[r] = ws
  181. widthmax = math.max(widthmax, widthsum[r])
  182. end
  183. end
  184. -- start building the array of images, if there are images
  185. if( imagecount > 0 ) then
  186. -- compute width of outer div
  187. local bodywidth = 0
  188. for r=1,rowcount do
  189. if( widthmax == widthsum[r] ) then
  190. bodywidth = widthmax + (3 + imagegap) * (perrow[r] - 1) + 12
  191. end
  192. end
  193. -- The body has a min-width of 100, which needs to be taken into account on specific widths
  194. bodywidth = math.max( 100, bodywidth - 8);
  195. local bg = pargs['background color'] or ''
  196. -- create the array of images
  197. local root = mw.html.create('div')
  198. root:addClass('thumb')
  199. root:addClass('tmulti')
  200. root:addClass(thumbclass[align] or 'tright')
  201. if( align == 'center' or align == 'centre' ) then
  202. root:addClass('center')
  203. end
  204. if( bg ~= '' ) then
  205. root:css('background-color', bg)
  206. end
  207. local div = root:tag('div')
  208. div:addClass('thumbinner')
  209. div:css('width', tostring(bodywidth) .. 'px')
  210. :css('max-width', tostring(bodywidth) .. 'px')
  211. if( bg ~= '' ) then
  212. div:css('background-color', bg)
  213. end
  214. if( border == 'infobox' or border == 'none') then
  215. div:css('border', 'none')
  216. end
  217. -- add the header
  218. if( isnotempty(header) ) then
  219. div:tag('div')
  220. :addClass('trow')
  221. :tag('div')
  222. :addClass('theader')
  223. :css('text-align', pargs['header_align'])
  224. :css('background-color', pargs['header_background'])
  225. :wikitext(header)
  226. end
  227. -- loop through the images
  228. local k = 0
  229. for r=1,rowcount do
  230. local rowdiv = div:tag('div'):addClass('trow');
  231. for j=1,perrow[r] do
  232. k = k + 1
  233. if( k <= imagecount ) then
  234. local imagediv = rowdiv:tag('div')
  235. imagediv:addClass('tsingle')
  236. if bg ~= '' then
  237. imagediv:css('background-color', bg);
  238. end
  239. if ((imagegap > 1) and (j < perrow[r])) then
  240. imagediv:css('margin-right', tostring(imagegap) .. 'px')
  241. end
  242. local i = imagenumbers[k]
  243. local img = pargs['image' .. i]
  244. local w = widths[k]
  245. imagediv:css('width', tostring(2 + w) .. 'px')
  246. :css('max-width', tostring(2 + w) .. 'px')
  247. imagediv:wikitext(renderImageCell(img, w, heights[k],
  248. pargs['link' .. i], pargs['alt' .. i],
  249. pargs['thumbtime' .. i], pargs['caption' .. i], capalign, imgstyle))
  250. end
  251. end
  252. end
  253. -- add the footer
  254. if( isnotempty(footer) ) then
  255. local falign = string.lower(pargs['footer_align'] or args['footer_align'] or 'left')
  256. falign = (falign == 'centre') and 'center' or falign
  257. div:tag('div')
  258. :addClass('trow')
  259. :css('display', (falign ~= 'left') and 'flow-root' or 'flex')
  260. :tag('div')
  261. :addClass('thumbcaption')
  262. :css('text-align', (falign ~= 'left') and falign or nil)
  263. :css('background-color', pargs['footer_background'])
  264. :wikitext(footer)
  265. end
  266. return tostring(root)
  267. end
  268. return ''
  269. end
  270. function p.render( frame )
  271. autoscaledimages = false
  272. nonautoscaledimages = false
  273. return frame:extensionTag {name = 'templatestyles', args = {src = 'Multiple image/styles.css'}}
  274. -- wrapper = ".tmulti" is inoperative
  275. .. renderMultipleImages( frame )
  276. end
  277. return p