词条 | Module:Jctint/core/sandbox |
释义 | local p = {} -- Package to be exported -- Change to "" upon deployment.local moduleSuffix = "/sandbox" local parserModuleName = "Module:Road data/parser" .. moduleSuffix -- Local version of string formatting functionlocal format = mw.ustring.format -- Store functions in a local variable to avoid expensive table lookups.local concat = table.concat local insert = table.insert -- Road data functionslocal roadDataModule = require("Module:Road data") -- Road data utility functionslocal util = require("Module:Road data/util") -- mw.html object for the generated rowlocal row -- Default row span for all columns (`jspan` = "junction span")local jspan -- Error typeslocal errorTypes = { convert = {cat = "Category:Jctint template using non-numeric parameter values", prefix = "#"}, type = {cat = "Category:Jctint template with invalid type"} } -- Error messages to be added to the outputlocal errors = {} -- A specification for self-closing HTML tag.local selfClosing = {selfClosing = true} -- Converts the distance specified in unit from `unit` specified in `unitdef`-- to the other supported unit. local function convert(unit, unitdef) if unit == nil or unitdef == nil then return {} end -- Import module to convert length. local lengths = util.convertLengths({[unitdef] = unit}) if lengths.error then -- An error occurred during conversion. errors.convert = lengths.error end return lengths end --- Prepare wikitext for a given location cell.local function locnSub(args, config, subType) local locns = {warnings = {}} local origParam local group local subTypeConfig = config[subType .. "_params"] or {subType} if args[subType .. "_special"] then locns[subType] = args[subType .. "_special"] return locns end local paramPrefix = subTypeConfig[#subTypeConfig] if paramPrefix and args[paramPrefix .. "_special"] then locns[subType] = args[paramPrefix .. "_special"] return locns end -- Find parameter. for _,p in ipairs(subTypeConfig) do if args[p] then origParam = p group = false break elseif args[p .. 1] then origParam = p group = true break end end if origParam then local subParts = {} -- Retrieve wikilinks for subdivisions. local num = 1 local paramSuffix = group and num or "" while num == 1 or group and args[origParam .. paramSuffix] do local param = origParam local saved = {} saved[param] = args[param] or false args[param] = args[origParam .. paramSuffix] if subType == "sub1" then -- Handle sub1area local sub1area_param = config.sub1area_param or "sub1area" saved.sub1area = args.sub1area or false args.sub1area = args[sub1area_param .. paramSuffix] elseif subType == "sub2" then -- Handle sub1dab and sub2area local sub1dab_param = config.sub1dab_param or "sub1dab" saved.sub1dab = args.sub1dab or false args.sub1dab = args[sub1dab_param .. paramSuffix] or args[sub1dab_param] local sub2area_param = config.sub2area_param or "sub2area" saved.sub2area = args.sub2area or false args.sub2area = args[sub2area_param .. paramSuffix] end while config[param] and config[param].alias do -- Resolve alias and save parameters. for key,value in pairs(config[param].alias) do if key == "param" then saved[value] = args[value] or false args[value] = args[param] param = value else saved[key] = args[key] or false args[key] = value end end end local subTypeCall = roadDataModule.locations(args, "jctint", group) insert(subParts, subTypeCall[subType]) util.addAll(locns.warnings, subTypeCall.warnings, true) -- Restore parameters. for key,value in pairs(saved) do args[key] = value or nil end num = num + 1 paramSuffix = group and num or "" end if group then if #subParts > 1 then -- Construct wikitext for multiple subs. local textParts = {} insert(textParts, subParts[1]) for i = 2, #subParts do insert(textParts, "–") if i % 2 ~= 0 then -- Odd subs after first begin a new line. insert(textParts, " end insert(textParts, subParts[i]) end local groupSuffix = args[origParam .. "_group"] or config[origParam] and config[origParam].group if groupSuffix then insert(textParts, format("%s%s", #subParts % 2 == 0 and " end if #subParts == 2 then local borderSuffix = config.bordersuffix or "border" if borderSuffix ~= "" then insert(textParts, " " .. borderSuffix) end elseif #subParts == 3 then insert(textParts, " tripoint") elseif #subParts == 4 then insert(textParts, " quadripoint") else insert(textParts, " multipoint") end locns[subType] = concat(textParts) else locns.warnings.group = "Singleton list for " .. origParam end else locns[subType] = concat(subParts) end end return locns end --- Prepare wikitext for location cells.local function locns(args) local parserModule = require(parserModuleName) local config = parserModule.parser(args, "jctrow", " config ") or {} local locns = {warnings = {}} local regionCall = roadDataModule.locations(args, "jctint") locns.region = regionCall.region util.addAll(locns.warnings, regionCall.warnings, true) local indepCityCall = locnSub(args, config, "indep_city") locns.indep_city = indepCityCall.indep_city util.addAll(locns.warnings, indepCityCall.warnings, true) if locns.indep_city then return locns end local sub1Call = locnSub(args, config, "sub1") locns.sub1 = sub1Call.sub1 util.addAll(locns.warnings, sub1Call.warnings, true) local sub2Call = locnSub(args, config, "sub2") locns.sub2 = sub2Call.sub2 util.addAll(locns.warnings, sub2Call.warnings, true) return locns end --- Creates cells for the location columns.local function locations(args) -- Unitary, e.g., state line local unitary = args.unitary -- Value to span all of the location columns if unitary then -- Text alignment of the cell contents, default to "left". local align = args.unitary_align or 'left' row:tag('td') -- Create unitary cell :attr('colspan', 3) -- spanning three possible columns :css('text-align', align) :wikitext(unitary) -- Store the contents of unitary in the cell. return end -- Prepare text for location cells. local locns = locns(args) -- Create cells for regular location columns. -- Row span for region; must be specified to display a region cell. local regionSpan = args.regionspan if regionSpan then row:tag('td') -- Create a region cell :attr('rowspan', regionSpan) -- Store region text in the cell. -- `region_special` argument overrides wikilinked `region` argument. :wikitext(args.region_special or locns.region) end -- Note below main text in the next column local sub1note = args.sub1_note -- check existence later -- Row span for the last location column, default to `jspan` local sub2span = args.sub2span or jspan -- Independent city local indepCityText = locns.indep_city -- Value to span both subdivision columns. if indepCityText then -- Display independent city. -- Text alignment of the cell contents, default to "left". local align = args.indep_city_align or 'left' local indepCityCell = row:tag('td') -- Create independent city cell :attr('colspan', 2) -- spanning two columns :attr('rowspan', sub2span) -- with the calculated row span. :css('text-align', align) :wikitext(indepCityText) -- Store the independent city in the cell. if sub1note then -- A note is provided. indepCityCell:tag('br', selfClosing) -- Add a line break to the cell. -- Add the note to the cell, within an HTML tag. indepCityCell:tag('small'):wikitext(sub1note) end return end -- Create two cells for the first- and second-level subdivisions. -- First-level subdivision, e.g., county local sub1Text = locns.sub1 -- Value for first-level subdivision column. if sub1Text then -- Display first-level subdivision. -- Row span for first-level subdivision, default to `jspan`. local sub1span = args.sub1span or jspan local sub1Cell = row:tag('td') -- Create first-level subdivision cell :attr('rowspan', sub1span) -- with the calculated row span. :wikitext(sub1Text) -- Store the first-level subdivision in the cell. if sub1note then -- A note is provided. sub1Cell:tag('br', selfClosing) -- Add a line break to the cell. -- Add the note to the cell, within an HTML tag. sub1Cell:tag('small'):wikitext(sub1note) end end -- Second-level subdivision, e.g., city and town local sub2Text = locns.sub2 -- Value for second-level subdivision column. if sub2Text then -- Display second-level subdivision. row:tag('td') -- Create second-level subdivision cell :attr('rowspan', sub2span) -- with the calculated row span. :wikitext(sub2Text) -- Store the second-level subdivision in the cell. end end --- Creates cells for the distance columns.local function units(args) -- Alternate units, e.g., California's postmiles. local alt_unit = args.altunit if alt_unit then -- Alternate units override standard units. -- Row span (`auspan` = "alt[ernate] unit span") local auspan = args.auspan or jspan -- Create the alternate unit cell as a header cell for the row, -- since it is usually unique within the table. row:tag('th'):attr('scope', 'row') :css('text-align', 'right') :attr('rowspan', auspan) :wikitext(alt_unit) -- Store the contents of alt_unit in the cell. else -- Convert numeric distances to a secondary unit, and display both units. -- Distance in the primary unit, or 'none' local unit = args.unit -- If `unit` is "none", no cells are displayed. if unit == "none" then return end local unitdef = args.unitdef or "km" -- The primary unit ('mi' or 'km') -- Convert and format the distance. local lengths = convert(unit, unitdef) -- Row span (`uspan` = "unit span") local uspan = args.uspan or jspan -- Create the primary unit cell as a header cell for the row, -- since it is usually unique within the table. local primary = row:tag('th'):attr('scope', 'row') :css('text-align', 'right') :attr('rowspan', uspan) -- Store the primary distance and any conversion error message in the cell. :wikitext(lengths[lengths.orig]) local secondary = row:tag('th'):attr('scope', 'row') -- Create the secondary unit cell. :css('text-align', 'right') :attr('rowspan', uspan) :wikitext(lengths[lengths.comp]) -- Store the secondary distance in the cell. local unit2 = args.unit2 if unit2 then -- A second distance is provided. local line = args.line -- A horizontal rule may be requested between the distances. if line then -- Add a horizontal rule to both cells. primary:tag('hr', selfClosing) secondary:tag('hr', selfClosing) else -- Add an en-dash and a line break to both cells. primary:wikitext('–'):tag('br', selfClosing) secondary:wikitext('–'):tag('br', selfClosing) end -- Convert and format the second distance. local lengths2 = convert(unit2, unitdef) -- Add the second distance and any conversion error message to the primary distance cell. primary:wikitext(lengths2[lengths2.orig]) -- Add the converted second distance to the secondary distance cell. secondary:wikitext(lengths2[lengths2.comp]) end local unit_ref = args.unit_ref if unit_ref then -- A reference is provided for the distance. primary:wikitext(unit_ref) -- Add reference to the primary distance cell. end end end -- Spec for formatting cell background colors and tooltip based on typeslocal typesSpec = {} --- Apply any type-derived coloring and tooltip to the given cell.local function applyTypeStyle(cell, multiple) cell:attr('title', typesSpec.title) :css('background', multiple and typesSpec.colors or typesSpec.color) if multiple and typesSpec.minWidth then -- minimum cell width to make enough room for all colors cell:css('min-width', format('%dpx', typesSpec.minWidth)) end end --- Creates a cell for places, such as bridges and rest areas.local function place(args) local place = args.place -- Contents of the place cell -- Do nothing if `place` is "none" if place == "none" then return end local colspan = 2 -- Initial column span local exit = args[1] -- Whether this table has exit number columns local named = args[2] -- Whether this table has named junction column -- Adjust column span if exit == "old" then colspan = colspan + 2 elseif exit == "exit" then colspan = colspan + 1 end if named == "name" then colspan = colspan + 1 end -- Row span (`pspan` = "place span") local pspan = args.pspan or jspan local placeCell = row:tag('td') -- Create place cell :css('text-align', 'center') :attr('colspan', colspan) :attr('rowspan', pspan) :wikitext(place) -- Store the place in the cell applyTypeStyle(placeCell, true) end --- Creates cells for exit number and named junction columns.local function exits(args) local exit = args[1] -- 'exit', 'old', or nil local named = args[2] -- 'name' or nil if exit == 'old' then -- Add old exit number cell local oldExits = {} if args.old then insert(oldExits, args.old) end local num = 0 repeat num = num + 1 local key = "old" .. num if args[key] then insert(oldExits, args[key]) end until num > 1 and args[key] == nil -- Row span (`ospan` = "old span") local ospan = args.ospan or jspan local oldExitCell = row:tag('td') -- Create old exit number cell :css('text-align', 'center') :css('background-color', '#d3d3d3') :attr('title', 'Former exit number') :attr('rowspan', ospan) if #oldExits > 2 then -- Create a collapsible table for many old exit numbers. local numOldExits = #oldExits local tbl = oldExitCell:tag("table") :attr("class", "collapsible collapsed") :css("margin", "auto") :css("border-collapse", "collapse") tbl:tag("th"):attr("scope", "col") local ul = tbl:tag("tr"):tag("td"):tag("div") :attr("class", "plainlist") :tag("ul") :css("text-align", "center") for num,oldExit in ipairs(oldExits) do if num < numOldExits then ul:tag("li"):wikitext(oldExit) end end -- Most recent number is always shown below the table. oldExitCell:wikitext(oldExits[numOldExits]) else -- Create an hlist for few old exit numbers. local ul = oldExitCell:tag("div") :attr("class", "hlist") :tag("ul") :css("text-align", "center") for _,oldExit in ipairs(oldExits) do ul:tag("li"):wikitext(oldExit) end end end if exit then -- "exit" or "old" is defined; add current exit number cell -- Row span (`espan` = "exit span") local espan = args.espan or jspan local exitCell = row:tag('td') -- Create exit number cell :css('text-align', 'center') :attr('rowspan', espan) :wikitext(args.exit) -- Store the exit number in the cell applyTypeStyle(exitCell) end if named then -- Junction list has a junction name column local namespan = args.namespan or jspan -- Row span local nameCell = row:tag('td') -- Create junction name cell :attr('rowspan', namespan) :wikitext(args.name) -- Store the junction name in the cell applyTypeStyle(nameCell) end end --- Creates cell for the destinations column.local function destinations(args) local road = args.road -- Contents of the destinations cell -- Do nothing if `road` is "none" if road == "none" then return end -- Column span (`rcspan` = "road column span"), default to 1 local rcspan = args.rcspan or 1 -- Row span (`rspan` = "road span") local rspan = args.rspan or jspan local destCell = row:tag('td') -- Create destination cell :attr('colspan', rcspan) :attr('rowspan', rspan) :wikitext(road) -- Store the destination in the cell applyTypeStyle(destCell) end --- Creates cell for the notes column.local function notes(args) local notes = args.notes -- Contents of the notes cell -- Do nothing if `notes` is "none" if notes == "none" then return end -- Row span (`nspan` = "notes span") local nspan = args.nspan or jspan local notesCell = row:tag('td') -- Create notes cell :attr('rowspan', nspan) :wikitext(notes) -- Store the notes in the cell applyTypeStyle(notesCell, true) end -- Returns a row in the junction list.-- Accessible from other Lua modules function p._jctint(args) jspan = args.jspan or 1 -- Global row span for all columns; defaults to 1 -- {{{type}}} argument to determine color and tooltips local argType = args.type if argType then -- {{{type}}} was passed local types = mw.text.split(argType, ",") table.sort(types, function(a, b) return a > b end) -- Type-based data for colors and tooltips local definedTypes = mw.loadData("Module:Road data/RJL types") local colors = {} local titles = {} for _,type in ipairs(types) do local typeSpec = definedTypes[string.lower(type)] -- Retrieve the type spec if typeSpec then insert(colors, typeSpec.color) insert(titles, 1, typeSpec.jctint) title = typeSpec.jctint -- Store the tooltip globally else errors.type = util.err("Invalid type: " .. argType) end end local colorWidth = 36 local colorSpec = {} local lastColor local colorCount = 0 for _,color in ipairs(colors) do if lastColor then insert(colorSpec, format("%s %dpx", lastColor, colorCount * colorWidth)) end insert(colorSpec, format("%s %dpx", color, colorCount * colorWidth)) lastColor = color colorCount = colorCount + 1 end if colorCount > 1 then typesSpec.colors = format("linear-gradient(-90deg, %s);", concat(colorSpec, ", ")) typesSpec.minWidth = (colorCount - 1) * colorWidth end typesSpec.color = lastColor typesSpec.title = concat(titles, ", ") end local root = mw.html.create() -- Create the root mw.html object to return -- Create the table row and store it globally row = root:tag('tr'):css('text-align', 'left') locations(args) -- Handle location arguments units(args) -- Handle distance arguments if args.place then -- {{{place}}} spans all columns to the right of the distances place(args) -- Create cell for place else exits(args) -- Handle exit/named junction arguments destinations(args) -- Handle destinations notes(args) -- Handle notes end -- Prepare error messages. local errorMsg = {} for key,msg in pairs(errors) do -- Add the transcluding page to an error tracking category. local prefix = errorTypes[key].prefix and errorTypes[key].prefix .. " " or "" insert(errorMsg, format("%s%s%%page%%", msg, errorTypes[key].cat, prefix)) end if #errorMsg > 0 then local page = mw.title.getCurrentTitle().prefixedText -- Get transcluding page's title -- Add error cell local msg = mw.ustring.gsub(concat(errorMsg, " "), "%%page%%", page) row:tag("td"):wikitext(msg) end -- Return the HTML code in the mw.html object as a string return tostring(root) end --- Entry function for {{jctint/core}}function p.jctint(frame) -- Import module function to work with passed arguments local getArgs = require('Module:Arguments').getArgs -- Gather passed arguments into easy-to-use table local args = getArgs(frame) return p._jctint(args) end return p -- Return package |
随便看 |
|
开放百科全书收录14589846条英语、德语、日语等多语种百科知识,基本涵盖了大多数领域的百科知识,是一部内容自由、开放的电子版国际百科全书。