| 第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 = ' 本' .. (cfg.sectionDefault or '頁面') | + | sect = ' 此' .. (cfg.sectionDefault or '頁面') |
| | elseif type(args.sect) == 'string' then | | elseif type(args.sect) == 'string' then |
| − | sect = ' 本' .. args.sect | + | sect = ' 此' .. args.sect |
| | end | | end |
| | local issue = args.issue | | local issue = args.issue |
| 第273行: |
第295行: |
| | 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 | | end |
| | if args.fix and args.fix ~= '' then | | if args.fix and args.fix ~= '' then |
| 第379行: |
第407行: |
| | if args.date and args.date ~= '' then | | if args.date and args.date ~= '' then |
| | date = args.date | | 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 | | elseif args.time and args.time ~= '' then |
| − | date = lang:formatDate('Y年n月', time) | + | date = lang:formatDate('Y年n月', args.time) |
| − | sortDay = lang:formatDate('j', time) | + | sortDay = lang:formatDate('j', args.time) |
| | sortDay = tonumber(sortDay) | | sortDay = tonumber(sortDay) |
| | sortDay = dayName[sortDay] | | sortDay = dayName[sortDay] |
| 第470行: |
第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('}}') |
| | )) | | )) |
| 第484行: |
第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. |
| 第504行: |
第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 self.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 |
| | | | |
| 第578行: |
第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) |
| 第591行: |
第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 |