第2行: |
第2行: |
| | | |
| -- Require necessary modules. | | -- Require necessary modules. |
− | local htmlBuilder = require('Module:HtmlBuilder') | + | local getArgs = require('Module:Arguments').getArgs |
| local categoryHandler = require('Module:Category handler').main | | local categoryHandler = require('Module:Category handler').main |
| local yesno = require('Module:Yesno') | | local yesno = require('Module:Yesno') |
第18行: |
第18行: |
| local trim = mw.text.trim | | local trim = mw.text.trim |
| | | |
− | local box = {}
| + | -------------------------------------------------------------------------------- |
| + | -- Helper functions |
| + | -------------------------------------------------------------------------------- |
| | | |
| local function getTitleObject(page, ...) | | local function getTitleObject(page, ...) |
第58行: |
第60行: |
| table.sort(nums) | | table.sort(nums) |
| return nums | | return nums |
| + | end |
| + | |
| + | -------------------------------------------------------------------------------- |
| + | -- Box class definition |
| + | -------------------------------------------------------------------------------- |
| + | |
| + | local box = {} |
| + | box.__index = box |
| + | |
| + | function box.new() |
| + | local obj = {} |
| + | setmetatable(obj, box) |
| + | return obj |
| end | | end |
| | | |
第105行: |
第120行: |
| nsVals[i] = format('"%s"', val) | | nsVals[i] = format('"%s"', val) |
| end | | end |
− | error('invalid ns parameter passed to box:addCat; valid values are ' .. mw.text.listToText(nsVals, nil, ' or ')) | + | error(' 無效的ns參數傳送到box:addCat ;有效的數值為' .. mw.text.listToText(nsVals, '、', ' 或')) |
| end | | end |
| self[tname] = self[tname] or {} | | self[tname] = self[tname] or {} |
第141行: |
第156行: |
| end | | end |
| tinsert(boxTypes, '"mbox"') | | tinsert(boxTypes, '"mbox"') |
− | error(format('invalid message box type "%s"; valid types are %s', tostring(boxType), mw.text.listToText(boxTypes)), 2) | + | error(format(' 無效的訊息框類型「%s 」;有效的類型為%s', tostring(boxType), mw.text.listToText(boxTypes)), 2) |
| end | | end |
| return cfg | | return cfg |
第188行: |
第203行: |
| if cfg.allowId then | | if cfg.allowId then |
| self.id = args.id | | self.id = args.id |
| + | self.name = args.name |
| + | if self.name then |
| + | self:addClass('box-' .. string.gsub(self.name,' ','_')) |
| + | end |
| end | | end |
| self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks') | | self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks') |
第195行: |
第214行: |
| if self.isSmall then | | if self.isSmall then |
| self:addClass(cfg.smallClass or 'mbox-small') | | self:addClass(cfg.smallClass or 'mbox-small') |
| + | end |
| + | if yesno(args.hidden) then |
| + | self:addClass('infobox editsection') |
| end | | end |
| self:addClass(self.typeClass) | | self:addClass(self.typeClass) |
第224行: |
第246行: |
| local sect | | local sect |
| if args.sect == '' then | | if args.sect == '' then |
− | sect = 'This ' .. (cfg.sectionDefault or 'page') | + | sect = ' 此' .. (cfg.sectionDefault or ' 頁面') |
| elseif type(args.sect) == 'string' then | | elseif type(args.sect) == 'string' then |
− | sect = 'This ' .. args.sect | + | sect = ' 此' .. args.sect |
| end | | end |
| local issue = args.issue | | local issue = args.issue |
第236行: |
第258行: |
| tinsert(issues, issue) | | tinsert(issues, issue) |
| tinsert(issues, text) | | tinsert(issues, text) |
− | self.issue = tconcat(issues, ' ') | + | self.issue = tconcat(issues) |
| end | | end |
| | | |
第270行: |
第292行: |
| | | |
| -- Get other values. | | -- Get other values. |
− | self.fix = args.fix ~= '' and args.fix or nil
| |
| local date | | local date |
| if args.date and args.date ~= '' then | | if args.date and args.date ~= '' then |
| date = args.date | | date = args.date |
− | elseif args.date == '' and self.isTemplatePage then | + | elseif args.time == '' and self.isTemplatePage then |
| date = lang:formatDate('Y年n月j日') | | date = lang:formatDate('Y年n月j日') |
| elseif args.time and args.time ~= '' then | | elseif args.time and args.time ~= '' then |
− | date = lang:formatDate('Y年n月j日', time) | + | date = lang:formatDate('Y年n月j日', args.time) |
| end | | end |
| if date then | | if date then |
− | self.date = format("<small> (%s )</small>", date) | + | local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月j日', date) -- 正規化日期 |
| + | if ok then |
| + | date = tempdate |
| + | end |
| + | end |
| + | if date then |
| + | self.date = string.format(" <small class='date-container'>''(<span class='date'>%s</span>)''</small>", date) |
| + | end |
| + | if args.fix and args.fix ~= '' then |
| + | self.fix = format("<br /><small>%s</small>", args.fix) |
| + | else |
| + | self.fix = '' |
| end | | end |
| self.info = args.info | | self.info = args.info |
第338行: |
第370行: |
| self.categoryParamNums = union(self.categoryParamNums, self.allNums) | | self.categoryParamNums = union(self.categoryParamNums, self.allNums) |
| -- The following is roughly equivalent to the old {{Ambox/category}}. | | -- The following is roughly equivalent to the old {{Ambox/category}}. |
− | local date = args.date | + | local date |
| + | local sortDay |
| + | local dayName = { |
| + | [1] = '㏠', |
| + | [2] = '㏡', |
| + | [3] = '㏢', |
| + | [4] = '㏣', |
| + | [5] = '㏤', |
| + | [6] = '㏥', |
| + | [7] = '㏦', |
| + | [8] = '㏧', |
| + | [9] = '㏨', |
| + | [10] = '㏩', |
| + | [11] = '㏪', |
| + | [12] = '㏫', |
| + | [13] = '㏬', |
| + | [14] = '㏭', |
| + | [15] = '㏮', |
| + | [16] = '㏯', |
| + | [17] = '㏰', |
| + | [18] = '㏱', |
| + | [19] = '㏲', |
| + | [20] = '㏳', |
| + | [21] = '㏴', |
| + | [22] = '㏵', |
| + | [23] = '㏶', |
| + | [24] = '㏷', |
| + | [25] = '㏸', |
| + | [26] = '㏹', |
| + | [27] = '㏺', |
| + | [28] = '㏻', |
| + | [29] = '㏼', |
| + | [30] = '㏽', |
| + | [31] = '㏾' |
| + | } |
| + | if args.date and args.date ~= '' then |
| + | date = args.date |
| + | local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月', date) -- 正規化日期 |
| + | if ok then |
| + | date = tempdate |
| + | end |
| + | elseif args.time and args.time ~= '' then |
| + | date = lang:formatDate('Y年n月', args.time) |
| + | sortDay = lang:formatDate('j', args.time) |
| + | sortDay = tonumber(sortDay) |
| + | sortDay = dayName[sortDay] |
| + | end |
| date = type(date) == 'string' and date | | date = type(date) == 'string' and date |
− | local preposition = 'from' | + | local preposition = ' 自' |
| for _, num in ipairs(self.categoryParamNums) do | | for _, num in ipairs(self.categoryParamNums) do |
| local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)] | | local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)] |
第347行: |
第425行: |
| allCat = type(allCat) == 'string' and allCat | | allCat = type(allCat) == 'string' and allCat |
| if mainCat and date and date ~= '' then | | if mainCat and date and date ~= '' then |
− | local catTitle = format('%s %s %s', mainCat, preposition, date) | + | local catTitle = format('%s%s%s', preposition, date, mainCat) |
− | self:addCat('main', catTitle) | + | if sortDay then |
| + | self:addCat('main', catTitle, sortDay) |
| + | else |
| + | self:addCat('main', catTitle) |
| + | end |
| catTitle = getTitleObject('Category:' .. catTitle) | | catTitle = getTitleObject('Category:' .. catTitle) |
| if not catTitle or not catTitle.exists then | | if not catTitle or not catTitle.exists then |
− | self:addCat('main', 'Articles with invalid date parameter in template') | + | self:addCat('main', ' 模板中使用无效日期参数的条目') |
| end | | end |
| elseif mainCat and (not date or date == '') then | | elseif mainCat and (not date or date == '') then |
第402行: |
第484行: |
| if self.invalidTypeError then | | if self.invalidTypeError then |
| local allSort = (self.nsid == 0 and 'Main:' or '') .. self.title.prefixedText | | local allSort = (self.nsid == 0 and 'Main:' or '') .. self.title.prefixedText |
− | self:addCat('all', 'Wikipedia message box parameter needs fixing', allSort) | + | self:addCat('all', ' 需要修复的信息框', allSort) |
| end | | end |
| if self.isSubstituted then | | if self.isSubstituted then |
− | self:addCat('all', 'Pages with incorrectly substituted templates') | + | self:addCat('all', ' 錯誤使用替換引用的頁面') |
| end | | end |
| | | |
第420行: |
第502行: |
| | | |
| function box:export() | | function box:export() |
− | local root = htmlBuilder.create() | + | local root = mw.html.create() |
| | | |
| -- Add the subst check error. | | -- Add the subst check error. |
| if self.isSubstituted and self.name then | | if self.isSubstituted and self.name then |
| root | | root |
− | .tag('b') | + | :tag('b') |
− | .addClass('error') | + | :addClass('error') |
− | .wikitext(format( | + | :wikitext(format( |
− | 'Template <code>%s[[Template:%s|%s]]%s</code> has been incorrectly substituted.', | + | ' 模板<code>%s[[Template:%s|%s]]%s</code> 被錯誤地替代。', |
| mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}') | | mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}') |
| )) | | )) |
第434行: |
第516行: |
| | | |
| -- Create the box table. | | -- Create the box table. |
− | local boxTable = root.tag('table') | + | local boxTable = root:tag('table') |
| boxTable | | boxTable |
− | .attr('id', self.id) | + | :attr('id', self.id) |
| for i, class in ipairs(self.classes or {}) do | | for i, class in ipairs(self.classes or {}) do |
| boxTable | | boxTable |
− | .addClass(class) | + | :addClass(class) |
| end | | end |
| boxTable | | boxTable |
− | .cssText(self.style) | + | :cssText(self.style) |
− | .attr('role', 'presentation') | + | :attr('role', 'presentation') |
| | | |
| -- Add the left-hand image. | | -- Add the left-hand image. |
− | local row = boxTable.tag('tr') | + | local row = boxTable:tag('tr') |
| if self.imageLeft then | | if self.imageLeft then |
− | local imageLeftCell = row.tag('td').addClass('mbox-image') | + | local imageLeftCell = row:tag('td'):addClass('mbox-image') |
| if self.imageCellDiv then | | if self.imageCellDiv then |
| -- If we are using a div, redefine imageLeftCell so that the image is inside it. | | -- If we are using a div, redefine imageLeftCell so that the image is inside it. |
第454行: |
第536行: |
| -- images in a div are wider than that, they may overlap with the text or cause | | -- images in a div are wider than that, they may overlap with the text or cause |
| -- other display problems. | | -- other display problems. |
− | imageLeftCell = imageLeftCell.tag('div').css('width', '52px') | + | imageLeftCell = imageLeftCell:tag('div'):css('width', '52px') |
| end | | end |
| imageLeftCell | | imageLeftCell |
− | .wikitext(self.imageLeft) | + | :wikitext(self.imageLeft) |
| elseif self.imageEmptyCell then | | elseif self.imageEmptyCell then |
| -- Some message boxes define an empty cell if no image is specified, and some don't. | | -- Some message boxes define an empty cell if no image is specified, and some don't. |
| -- The old template code in templates where empty cells are specified gives the following hint: | | -- The old template code in templates where empty cells are specified gives the following hint: |
| -- "No image. Cell with some width or padding necessary for text cell to have 100% width." | | -- "No image. Cell with some width or padding necessary for text cell to have 100% width." |
− | row.tag('td') | + | row:tag('td') |
− | .addClass('mbox-empty-cell') | + | :addClass('mbox-empty-cell') |
− | .cssText(self.imageEmptyCellStyle) | + | :cssText(self.imageEmptyCellStyle) |
| end | | end |
| | | |
| -- Add the text. | | -- Add the text. |
− | local textCell = row.tag('td').addClass('mbox-text') | + | local textCell = row:tag('td'):addClass('mbox-text') |
| if self.useCollapsibleTextFields then | | if self.useCollapsibleTextFields then |
| -- The message box uses advanced text parameters that allow things to be collapsible. At the | | -- The message box uses advanced text parameters that allow things to be collapsible. At the |
| -- moment, only ambox uses this. | | -- moment, only ambox uses this. |
| textCell | | textCell |
− | .cssText(self.textstyle) | + | :cssText(self.textstyle) |
− | local textCellSpan = textCell.tag('span') | + | local textCellSpan = textCell:tag('span') |
| textCellSpan | | textCellSpan |
− | .addClass('mbox-text-span') | + | :addClass('mbox-text-span') |
− | .wikitext(self.issue) | + | :wikitext(self.issue) |
| if not self.isSmall then | | if not self.isSmall then |
| textCellSpan | | textCellSpan |
− | .tag('span') | + | :tag('span') |
− | .addClass('hide-when-compact') | + | :addClass('hide-when-compact') |
− | .wikitext(self.talk and ' ' .. self.talk) | + | :wikitext(self.talk and self.talk) |
| end | | end |
| textCellSpan | | textCellSpan |
− | .wikitext(self.date and ' ' .. self.date) | + | :wikitext(self.date and self.date) |
− | if not self.isSmall and args.fix ~= '' then | + | if not self.isSmall and self.fix ~= '' then |
| textCellSpan | | textCellSpan |
− | .tag('span') | + | :tag('span') |
− | .addClass('hide-when-compact') | + | :addClass('hide-when-compact') |
− | .wikitext(self.fix and ' ' .. self.fix) | + | :wikitext(self.fix and self.fix) |
| end | | end |
| if not self.isSmall then | | if not self.isSmall then |
| textCellSpan | | textCellSpan |
− | .tag('span') | + | :tag('span') |
− | .addClass('hide-when-compact') | + | :addClass('hide-when-compact') |
− | .wikitext(self.info and ' ' .. self.info) | + | :wikitext(self.info and self.info) |
| end | | end |
| else | | else |
| -- Default text formatting - anything goes. | | -- Default text formatting - anything goes. |
| textCell | | textCell |
− | .cssText(self.textstyle) | + | :cssText(self.textstyle) |
− | .wikitext(self.text) | + | :wikitext(self.text) |
| end | | end |
| | | |
| -- Add the right-hand image. | | -- Add the right-hand image. |
| if self.imageRight then | | if self.imageRight then |
− | local imageRightCell = row.tag('td').addClass('mbox-imageright') | + | local imageRightCell = row:tag('td'):addClass('mbox-imageright') |
| if self.imageCellDiv then | | if self.imageCellDiv then |
− | imageRightCell = imageRightCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it. | + | imageRightCell = imageRightCell:tag('div'):css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it. |
| end | | end |
| imageRightCell | | imageRightCell |
− | .wikitext(self.imageRight) | + | :wikitext(self.imageRight) |
| end | | end |
| | | |
| -- Add the below row. | | -- Add the below row. |
| if self.below then | | if self.below then |
− | boxTable.tag('tr') | + | boxTable:tag('tr') |
− | .tag('td') | + | :tag('td') |
− | .attr('colspan', self.imageRight and '3' or '2') | + | :attr('colspan', self.imageRight and '3' or '2') |
− | .addClass('mbox-text') | + | :addClass('mbox-text') |
− | .cssText(self.textstyle) | + | :cssText(self.textstyle) |
− | .wikitext(self.below) | + | :wikitext(self.below) |
| end | | end |
| | | |
第528行: |
第610行: |
| if self.invalidTypeError then | | if self.invalidTypeError then |
| root | | root |
− | .tag('div') | + | :tag('div') |
− | .css('text-align', 'center') | + | :css('text-align', 'center') |
− | .wikitext(format('This message box is using an invalid "type=%s" parameter and needs fixing.', self.type or '')) | + | :wikitext(format(' 此訊息框使用無效的「type=%s 」參數,需要修復。', self.type or '')) |
| end | | end |
| | | |
| -- Add categories. | | -- Add categories. |
| root | | root |
− | .wikitext(self.categories) | + | :wikitext(self.categories) |
| | | |
| return tostring(root) | | return tostring(root) |
第541行: |
第623行: |
| | | |
| local function main(boxType, args) | | local function main(boxType, args) |
− | box:setTitle(args) | + | local outputBox = box.new() |
− | local cfg = box:getConfig(boxType) | + | outputBox:setTitle(args) |
− | args = box:removeBlankArgs(cfg, args) | + | local cfg = outputBox:getConfig(boxType) |
− | box:setBoxParameters(cfg, args) | + | args = outputBox:removeBlankArgs(cfg, args) |
− | return box:export() | + | outputBox:setBoxParameters(cfg, args) |
| + | return outputBox:export() |
| end | | end |
| | | |
| local function makeWrapper(boxType) | | local function makeWrapper(boxType) |
| return function (frame) | | return function (frame) |
− | -- If called via #invoke, use the args passed into the invoking | + | local args = getArgs(frame, {trim = false, removeBlanks = false}) |
− | -- template, or the args passed to #invoke if any exist. Otherwise
| |
− | -- assume args are being passed directly in from the debug console
| |
− | -- or from another Lua module.
| |
− | local origArgs
| |
− | if frame == mw.getCurrentFrame() then
| |
− | origArgs = frame:getParent().args
| |
− | for k, v in pairs(frame.args) do
| |
− | origArgs = frame.args
| |
− | break
| |
− | end
| |
− | else
| |
− | origArgs = frame
| |
− | end
| |
− | -- Trim whitespace.
| |
− | local args = {}
| |
− | for k, v in pairs(origArgs) do
| |
− | if type(v) == 'string' then
| |
− | v = trim(v)
| |
− | end
| |
− | args[k] = v
| |
− | end
| |
| return main(boxType, args) | | return main(boxType, args) |
| end | | end |