Difference between revisions of "Module:Jctint/core/sandbox"
Jump to navigation
Jump to search
blackwiki>Jackmcbarn (conditionally load Module:Arguments and avoid unnecessary use of ustring) |
m (50 revisions imported) |
||
| (41 intermediate revisions by 5 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} -- Package to be exported | local p = {} -- Package to be exported | ||
| − | local | + | -- Change to "" upon deployment. |
| + | local moduleSuffix = "/sandbox" | ||
| − | local | + | local parserModuleName = "Module:Road data/parser" .. moduleSuffix |
| − | + | -- Local version of string formatting function | |
| − | + | local format = mw.ustring.format | |
| − | local | + | -- Local version of string trimming function |
| − | local | + | local trim = mw.text.trim |
| − | local | + | -- Store this function in a local variable to avoid expensive table lookups. |
| + | local insert = table.insert | ||
| − | local | + | -- mw.html object for the generated row |
| − | + | local row | |
| − | + | -- Default row span for all columns (`jspan` = "junction span") | |
| − | if | + | local jspan |
| + | -- Any error messages produced that will be added to the output | ||
| + | local errorMsg = {} | ||
| + | |||
| + | -- 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 util = require("Module:Road data/util") | ||
| + | local lengths = util.convertLengths({[unitdef] = unit}) | ||
| + | if lengths.error then -- An error occurred during conversion. | ||
| + | -- Add the transcluding page to an error tracking category. | ||
local page = mw.title.getCurrentTitle() -- Get transcluding page's title | local page = mw.title.getCurrentTitle() -- Get transcluding page's title | ||
local pagename = page.prefixedText -- Extract page's full title as string | local pagename = page.prefixedText -- Extract page's full title as string | ||
| − | local category = format("[[Category:Jctint template using non-numeric parameter values|# %s]]", pagename) | + | -- Create category string |
| − | + | local category = format("[[Category:Jctint template using non-numeric parameter values|# %s]]", pagename) | |
| − | + | insert(errorMsg, category) -- Add error category to error message table. | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| − | + | return lengths | |
| − | |||
| − | return | ||
end | end | ||
| + | --- Creates cells for the location columns. | ||
local function locations(args) | local function locations(args) | ||
| − | -- | + | -- Unitary, e.g., state line |
| − | local unitary = args.unitary -- | + | local unitary = args.unitary -- Value to span all of the location columns |
if unitary then | if unitary then | ||
| − | local | + | -- 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 | |
| − | -- | + | |
| − | + | -- Create cells for regular location columns. | |
| − | local | + | |
| + | -- Region, for disambiguation and potentially for display | ||
| + | local region = args.region | ||
| + | if region or args.region_special then | ||
| + | -- Row span for region; must be specified to display a region cell. | ||
| + | local regionSpan = args.regionspan | ||
if regionSpan then | 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 format("[[%s]]", region)) | ||
end | end | ||
| − | + | end | |
| − | + | ||
| − | + | -- Primary topic requires no specialization to supplied locations. | |
| − | + | local primaryTopic = args.primary_topic ~= 'no' | |
| − | local | + | |
| − | + | -- Note below main text in the next column | |
| − | if | + | local sub1note = args.sub1_note -- check existence later |
| − | + | -- Row span for the last location column, default to `jspan` | |
| − | + | local sub2span = args.sub2span or jspan | |
| − | indepCityCell: | + | |
| − | + | -- Independent city | |
| − | + | local indepCityText -- Value to span both subdivision columns. | |
| − | + | if args.indep_city_special then | |
| − | + | indepCityText = args.indep_city_special -- Overrides `indep_city` argument. | |
| − | + | elseif args.indep_city then | |
| − | + | local indepCity = args.indep_city | |
| − | + | local cityLink -- Wikilink for independent city | |
| − | + | if primaryTopic then | |
| + | cityLink = format('[[%s]]', indepCity) | ||
| + | elseif region then | ||
| + | -- Specialize independent city to the region. | ||
| + | cityLink = format('[[%s, %s|%s]]', indepCity, region, indepCity) | ||
| + | end | ||
| + | if cityLink then | ||
| + | indepCityText = "[[Independent city|City]] of " .. cityLink | ||
| + | end | ||
| + | end | ||
| + | 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 <small> 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 | ||
| + | -- Name of the type of subdivision, e.g., "County" and "Parish" | ||
| + | local sub1name = args.sub1name -- check existence later | ||
| + | local sub1Text -- Value for first-level subdivision column. | ||
| + | if args.sub1_special then | ||
| + | sub1Text = args.sub1_special -- Overrides `sub1` argument. | ||
| + | elseif args.sub1 then | ||
| + | local sub1 = args.sub1 | ||
| + | if primaryTopic then | ||
| + | -- Add type (if specified) to wikilink for first-level subdivision. | ||
| + | local sub1Link = sub1name and format("%s %s", sub1, sub1name) or sub1 | ||
| + | sub1Text = format('[[%s|%s]]', sub1Link, sub1) | ||
| + | elseif region and sub1name then | ||
| + | -- Add type to first-level subdivision. | ||
| + | local sub1Typed = trim(format('%s %s', sub1, sub1name)) | ||
| + | -- Specialize first-level subdivision, with type added, to the region. | ||
| + | sub1Text = format('[[%s, %s|%s]]', sub1Typed, region, sub1) | ||
| + | end | ||
| + | end | ||
| + | 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 <small> tag. | ||
| + | sub1Cell:tag('small'):wikitext(sub1note) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | -- Second-level subdivision, e.g., city and town | ||
| + | local sub2Text -- Value for second-level subdivision column. | ||
| + | if args.sub2_special then | ||
| + | sub2Text = args.sub2_special -- Overrides `sub2` argument. | ||
| + | elseif args.sub2 then | ||
| + | local sub2 = args.sub2 | ||
| + | if sub2 == "none" or sub2 == " " then | ||
| + | sub2Text = "​" -- Zero-width space | ||
| + | elseif primaryTopic then | ||
| + | sub2Text = format("[[%s]]", sub2) | ||
| + | else | ||
| + | local sub2Link = {sub2} | ||
| + | local sub2Name = sub2 | ||
| + | -- Type of area, e.g., city and village, as a form of disambiguation | ||
| + | local area = args.area | ||
| + | if area then | ||
| + | insert(sub2Link, format(' (%s)', area)) -- Add area to wikilink. | ||
| + | local areas = { -- table of different area types | ||
| + | borough = "Borough", | ||
| + | city = "City", | ||
| + | community = "Community", | ||
| + | CDP = "Community", | ||
| + | hamlet = "Hamlet", | ||
| + | town = "Town", | ||
| + | village = "Village", | ||
| + | ["unorganized territory"] = "Unorganized Territory" | ||
| + | } | ||
| + | -- Add area name to displayed wikitext. | ||
| + | sub2Name = format("%s of %s", areas[area], sub2Name) | ||
end | end | ||
| − | + | insert(sub2Link, ", ") | |
| − | + | -- Some second-level subdivisions are not unique in a given region. | |
| − | + | -- `sub1dab` is the first-level subdivision to be used for disambiguation. | |
| + | local sub1dab = args.sub1dab | ||
| + | if sub1dab and sub1name then | ||
| + | insert(sub2Link, trim(format('%s %s', sub1dab, sub1name)) .. ", ") | ||
end | end | ||
| − | + | if region then | |
| − | + | insert(sub2Link, region) -- Add region to wikilink | |
| − | |||
| − | |||
| − | |||
| − | if | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| + | |||
| + | sub2Text = format("[[%s|%s]]", table.concat(sub2Link), sub2Name) | ||
end | end | ||
| + | end | ||
| + | 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 | ||
end | end | ||
| − | + | --- Creates cells for the distance columns. | |
| − | + | local function units(args) | |
| − | + | -- Alternate units, e.g., California's postmiles. | |
| − | if alt_unit then -- Alternate units | + | local alt_unit = args.altunit |
| − | local | + | 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. | |
| − | else -- | + | row:tag('th'):attr('scope', 'row') |
| − | + | :css('text-align', 'right') | |
| − | if unit | + | :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. | |
| − | primary:wikitext( | + | 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], lengths.error) | |
| − | + | local secondary = row:tag('td') -- Create the secondary unit cell. | |
| − | + | :css('text-align', 'right') | |
| − | + | :css('background-color', '#eaecf0') | |
| − | + | :attr('rowspan', uspan) | |
| − | + | :wikitext(lengths[lengths.comp]) -- Store the secondary distance in the cell. | |
| + | |||
| + | 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 | ||
| + | |||
| + | 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 | end | ||
| − | + | -- Convert and format the second distance. | |
| − | local | + | local lengths2 = convert(unit2, unitdef) |
| − | + | -- Add the second distance and any conversion error message to the primary distance cell. | |
| + | primary:wikitext(lengths2[lengths2.orig], lengths2.error) | ||
| + | -- Add the converted second distance to the secondary distance cell. | ||
| + | secondary:wikitext(lengths2[lengths2.comp]) | ||
| + | end | ||
| + | |||
| + | local unit2_ref = args.unit2_ref | ||
| + | if unit2_ref then -- A reference is provided for the distance. | ||
| + | primary:wikitext(unit2_ref) -- Add reference to the primary distance cell. | ||
end | end | ||
end | end | ||
end | end | ||
| − | + | -- Color specified by any supplied type | |
| − | + | local color | |
| − | + | -- Tooltip specified by any supplied type | |
| − | local | + | local title |
| − | + | ||
| − | + | --- Apply any type-derived coloring and tooltip to the given cell. | |
| − | local colspan -- | + | local function applyTypeStyle(cell) |
| − | local exit = args[1] -- Whether this table has exit | + | cell:attr('title', title):css('background-color', color) |
| − | local named = args[2] -- Whether this table | + | 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 | |
| − | elseif exit == | + | 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 | end | ||
| − | tag | + | 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) | ||
end | end | ||
| − | + | --- Creates cells for exit number and named junction columns. | |
| − | + | local function exits(args) | |
| − | local exit = args[1] -- | + | local exit = args[1] -- 'exit', 'old', or nil |
| − | local named = args[2] -- | + | local named = args[2] -- 'name' or nil |
| − | + | ||
if exit == 'old' then -- Add old exit number cell | if exit == 'old' then -- Add old exit number cell | ||
| − | local | + | -- Row span (`ospan` = "old span") |
| − | + | local ospan = args.ospan or jspan | |
| − | + | row:tag('td') -- Create old exit number cell | |
| + | :css('text-align', 'center') | ||
| + | :css('background-color', '#d3d3d3') | ||
| + | :attr('title', 'Former exit number') | ||
| + | :attr('rowspan', ospan) | ||
| + | :wikitext(args.old) -- Store the old exit number in the cell | ||
end | end | ||
| − | + | ||
| − | if exit | + | 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 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 | end | ||
| − | + | ||
| − | if named | + | if named then -- Junction list has a junction name column |
| − | + | local namespan = args.namespan or jspan -- Row span | |
| − | local namespan = args.namespan or jspan | + | 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 | ||
end | end | ||
| − | function destinations(args) | + | --- 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 | |
| − | local | + | -- 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 | local notes = args.notes -- Contents of the notes cell | ||
| − | if notes | + | -- 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) | ||
end | end | ||
| + | --- | ||
| + | -- Returns a row in the junction list. | ||
| + | -- Accessible from other Lua modules | ||
function p._jctint(args) | 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 | |
| − | jspan = args.jspan -- | + | local argType = args.type |
| − | + | if argType then -- {{{type}}} was passed | |
| − | if | + | -- Type-based data for colors and tooltips |
| − | local typeData = types[string.lower( | + | if argType == 'mplex' then |
| + | local page = mw.title.getCurrentTitle() -- Get transcluding page's title | ||
| + | local pagename = page.prefixedText -- Extract page's full title as string | ||
| + | insert(errorMsg, | ||
| + | format("[[Category:Jctint template with invalid type|$ %s]]", pagename)) | ||
| + | end | ||
| + | local types = mw.loadData("Module:Road data/RJL types") | ||
| + | local typeData = types[string.lower(argType)] -- Retrieve the type data | ||
if typeData then | if typeData then | ||
color = typeData.color -- Store the color globally | color = typeData.color -- Store the color globally | ||
title = typeData.jctint -- Store the tooltip globally | title = typeData.jctint -- Store the tooltip globally | ||
| − | else -- | + | else |
| + | -- Add error category to error message table. | ||
local page = mw.title.getCurrentTitle() -- Get transcluding page's title | local page = mw.title.getCurrentTitle() -- Get transcluding page's title | ||
local pagename = page.prefixedText -- Extract page's full title as string | local pagename = page.prefixedText -- Extract page's full title as string | ||
| − | + | insert(errorMsg, | |
| + | format("[[Category:Jctint template with invalid type|%s]]", pagename)) | ||
end | end | ||
end | end | ||
| − | local root = mw.html.create() -- Create the root mw.html object | + | |
| − | row = root:tag('tr'):css('text-align', 'left') | + | 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 | locations(args) -- Handle location arguments | ||
units(args) -- Handle distance arguments | units(args) -- Handle distance arguments | ||
| Line 288: | Line 404: | ||
else | else | ||
exits(args) -- Handle exit/named junction arguments | exits(args) -- Handle exit/named junction arguments | ||
| − | destinations(args) -- Handle destinations | + | destinations(args) -- Handle destinations |
| + | notes(args) -- Handle notes | ||
end | end | ||
| − | + | ||
| − | + | -- Return the HTML code in the mw.html object as a string, plus any error messages | |
| + | return tostring(root) .. table.concat(errorMsg) | ||
end | end | ||
| + | --- Entry function for {{jctint/core}} | ||
function p.jctint(frame) | 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 | end | ||
return p -- Return package | return p -- Return package | ||
Latest revision as of 05:49, 27 September 2020
Documentation for this module may be created at Module:Jctint/core/sandbox/doc
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 function
local format = mw.ustring.format
-- Local version of string trimming function
local trim = mw.text.trim
-- Store this function in a local variable to avoid expensive table lookups.
local insert = table.insert
-- mw.html object for the generated row
local row
-- Default row span for all columns (`jspan` = "junction span")
local jspan
-- Any error messages produced that will be added to the output
local errorMsg = {}
-- 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 util = require("Module:Road data/util")
local lengths = util.convertLengths({[unitdef] = unit})
if lengths.error then -- An error occurred during conversion.
-- Add the transcluding page to an error tracking category.
local page = mw.title.getCurrentTitle() -- Get transcluding page's title
local pagename = page.prefixedText -- Extract page's full title as string
-- Create category string
local category = format("[[Category:Jctint template using non-numeric parameter values|# %s]]", pagename)
insert(errorMsg, category) -- Add error category to error message table.
end
return lengths
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
-- Create cells for regular location columns.
-- Region, for disambiguation and potentially for display
local region = args.region
if region or args.region_special then
-- 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 format("[[%s]]", region))
end
end
-- Primary topic requires no specialization to supplied locations.
local primaryTopic = args.primary_topic ~= 'no'
-- 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 -- Value to span both subdivision columns.
if args.indep_city_special then
indepCityText = args.indep_city_special -- Overrides `indep_city` argument.
elseif args.indep_city then
local indepCity = args.indep_city
local cityLink -- Wikilink for independent city
if primaryTopic then
cityLink = format('[[%s]]', indepCity)
elseif region then
-- Specialize independent city to the region.
cityLink = format('[[%s, %s|%s]]', indepCity, region, indepCity)
end
if cityLink then
indepCityText = "[[Independent city|City]] of " .. cityLink
end
end
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 <small> 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
-- Name of the type of subdivision, e.g., "County" and "Parish"
local sub1name = args.sub1name -- check existence later
local sub1Text -- Value for first-level subdivision column.
if args.sub1_special then
sub1Text = args.sub1_special -- Overrides `sub1` argument.
elseif args.sub1 then
local sub1 = args.sub1
if primaryTopic then
-- Add type (if specified) to wikilink for first-level subdivision.
local sub1Link = sub1name and format("%s %s", sub1, sub1name) or sub1
sub1Text = format('[[%s|%s]]', sub1Link, sub1)
elseif region and sub1name then
-- Add type to first-level subdivision.
local sub1Typed = trim(format('%s %s', sub1, sub1name))
-- Specialize first-level subdivision, with type added, to the region.
sub1Text = format('[[%s, %s|%s]]', sub1Typed, region, sub1)
end
end
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 <small> tag.
sub1Cell:tag('small'):wikitext(sub1note)
end
end
-- Second-level subdivision, e.g., city and town
local sub2Text -- Value for second-level subdivision column.
if args.sub2_special then
sub2Text = args.sub2_special -- Overrides `sub2` argument.
elseif args.sub2 then
local sub2 = args.sub2
if sub2 == "none" or sub2 == " " then
sub2Text = "​" -- Zero-width space
elseif primaryTopic then
sub2Text = format("[[%s]]", sub2)
else
local sub2Link = {sub2}
local sub2Name = sub2
-- Type of area, e.g., city and village, as a form of disambiguation
local area = args.area
if area then
insert(sub2Link, format(' (%s)', area)) -- Add area to wikilink.
local areas = { -- table of different area types
borough = "Borough",
city = "City",
community = "Community",
CDP = "Community",
hamlet = "Hamlet",
town = "Town",
village = "Village",
["unorganized territory"] = "Unorganized Territory"
}
-- Add area name to displayed wikitext.
sub2Name = format("%s of %s", areas[area], sub2Name)
end
insert(sub2Link, ", ")
-- Some second-level subdivisions are not unique in a given region.
-- `sub1dab` is the first-level subdivision to be used for disambiguation.
local sub1dab = args.sub1dab
if sub1dab and sub1name then
insert(sub2Link, trim(format('%s %s', sub1dab, sub1name)) .. ", ")
end
if region then
insert(sub2Link, region) -- Add region to wikilink
end
sub2Text = format("[[%s|%s]]", table.concat(sub2Link), sub2Name)
end
end
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], lengths.error)
local secondary = row:tag('td') -- Create the secondary unit cell.
:css('text-align', 'right')
:css('background-color', '#eaecf0')
:attr('rowspan', uspan)
:wikitext(lengths[lengths.comp]) -- Store the secondary distance in the cell.
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
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], lengths2.error)
-- Add the converted second distance to the secondary distance cell.
secondary:wikitext(lengths2[lengths2.comp])
end
local unit2_ref = args.unit2_ref
if unit2_ref then -- A reference is provided for the distance.
primary:wikitext(unit2_ref) -- Add reference to the primary distance cell.
end
end
end
-- Color specified by any supplied type
local color
-- Tooltip specified by any supplied type
local title
--- Apply any type-derived coloring and tooltip to the given cell.
local function applyTypeStyle(cell)
cell:attr('title', title):css('background-color', color)
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)
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
-- Row span (`ospan` = "old span")
local ospan = args.ospan or jspan
row:tag('td') -- Create old exit number cell
:css('text-align', 'center')
:css('background-color', '#d3d3d3')
:attr('title', 'Former exit number')
:attr('rowspan', ospan)
:wikitext(args.old) -- Store the old exit number in the cell
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)
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
-- Type-based data for colors and tooltips
if argType == 'mplex' then
local page = mw.title.getCurrentTitle() -- Get transcluding page's title
local pagename = page.prefixedText -- Extract page's full title as string
insert(errorMsg,
format("[[Category:Jctint template with invalid type|$ %s]]", pagename))
end
local types = mw.loadData("Module:Road data/RJL types")
local typeData = types[string.lower(argType)] -- Retrieve the type data
if typeData then
color = typeData.color -- Store the color globally
title = typeData.jctint -- Store the tooltip globally
else
-- Add error category to error message table.
local page = mw.title.getCurrentTitle() -- Get transcluding page's title
local pagename = page.prefixedText -- Extract page's full title as string
insert(errorMsg,
format("[[Category:Jctint template with invalid type|%s]]", pagename))
end
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
-- Return the HTML code in the mw.html object as a string, plus any error messages
return tostring(root) .. table.concat(errorMsg)
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