Module:Track gauge/autodocument/sandbox
![]() | This is the module sandbox page for Module:Track gauge/autodocument (diff). |
![]() | This module depends on the following other modules: |
![]() | This module uses TemplateStyles: |
This module documents the Track gauge/data data page of {{Track gauge}}. Its main product is Template:Track gauge/doc/input options.
Gauges
documentGauge
Can list in complete tableform one, multiple or all gauges listed in the /data page. Gauges defined in both metric and imperial are grouped into one row.
Per gauge size a link to the category:Articles that mentions this gauge ... is added.
#invoke functions
checkData documentGauge catContent catMentions createCatMentions documentGaugeSizeFromTitle catSortFromTitle
Parameters
|1= alias |1<!--???-->= (datafile for checkData) |n=all (list) |docfrom= |docto= |doctitle= |docstate= |docstats= |displaynotfound= |docsortlabel= |docreturnargs=
Parser limits (expensive functions)
Module:Track gauge/autodocument uses expensive function calls (especially the documentGauge
listing). The wiki parser only allows 500 such calls in one page. As of July 2014, this number is almost reached in (~475 in Template:Track gauge/doc/input options). When, after adding new entries to /data or /extra, the number is reached, a "Script error" will show.
Best practice is to prevent this error: adding content category name to the /data, even if they have default name pattern or do not exist:
["contentcat"] = "5 ft 3 in gauge railways",
-- or
["contentcat"] = "",
This way, these category pages are not checked for existence.
See also
-- This module implements the {{RailGauge}} template.
-- Input can be predefined aliases (see the /data module page)
local p = {}
local gaugeDataAll = nil
local dataPageName = 'Module:RailGauge/data/sandbox' --SANDBOX
-----------------------------------------------------------------------------------
-- formatUnitPlaintext
-- Pattern '00016.5 mm' for tablesort and catsort. Can be wrapped in class="sortkey"
-----------------------------------------------------------------------------------
local function formatUnitPlaintext( rgData, unit, fmtZeroPadding, toFracChar )
-- Returns plaintext (ASCII) only. No css.
if rgData == nil then
return ''
end
if ( unit or rgData.def ) == 'imp' then
local ft = ''
local inch = ''
local frac = ''
if rgData.ft then
ft = rgData.ft .. ' ft'
end
if rgData.num then
frac = ' ' .. rgData.num .. '/' .. rgData.den
if toFracChar then
-- as used in contentCat pagenames
if frac == ' 1/8' then
frac = '⅛'
elseif frac == ' 1/4' then
frac = '¼'
elseif frac == ' 3/8' then
frac = '⅜'
elseif frac == ' 1/2' then
frac = '½'
elseif frac == ' 3/4' then
frac = '¾'
elseif frac == ' 7/8' then
frac = '⅞'
else
frac = frac .. ' (error: fraction character missing in module:RailGauge)'
end
end
if rgData["in"] then
frac = ' ' .. rgData["in"] .. frac .. ' in'
else
frac = frac .. ' in'
end
else
if rgData["in"] then
inch = ' ' .. rgData["in"] .. ' in'
end
end
return mw.text.trim( ft .. inch .. frac )
else
-- metric ( mm )
if fmtZeroPadding == nil or tonumber( fmtZeroPadding ) <= 0 then
return rgData.id .. ' mm'
else
return string.rep( '0',
fmtZeroPadding - string.len( math.floor( tonumber( rgData.id ) ) ) )
.. rgData.id .. ' mm'
end
end
end
-----------------------------------------------------------------------------------
-- anchor -- Anchor text *here* is: <span id="1000 mm">; anchor *there* is: #1000 mm.
-----------------------------------------------------------------------------------
local function anchor( rgEntry, unit, herethere )
local html = require( 'Module:HtmlBuilder' )
if rgEntry == nil then
return ''
end
unit = unit or rgEntry.def1
local anch = formatUnitPlaintext( rgEntry,unit, 0 )
if herethere == 'there' then -- Untested, April 2014
anch = '#' .. anch
else
anch = html.create().tag( 'span' ).attr( 'id', anch )
end
return tostring( anch )
end
-----------------------------------------------------------------------------------
-- catMentionsGaugeSize -- category name for "article mentions gauge" categories
-----------------------------------------------------------------------------------
local function catMentionsGaugeSize( mmSize, catSort, pagename, show, plaintext )
local cat -- hereo
-- Category page name. mmSize has format of id ( like '16.5' ).
cat = 'Category:Articles that mention rail gauge size' .. ' ' .. mmSize .. ' mm'
if plaintext then
return cat
elseif show then
-- uses colon and wikilabel; no catsort
local label = '|cat:mentionings'
cat = '[[:'.. cat .. label .. ']]'
else
if ( catSort or '' ) ~= '' then
catSort = '|' .. catSort
else
catSort = ''
end
cat = '[['.. cat .. catSort .. ']]'
end
return cat
end
-----------------------------------------------------------------------------------
-- catMentionsGaugeSizeParent -- Parent of all "mentions" categories
-----------------------------------------------------------------------------------
local function catMentionsGaugeSizeParent( show )
local cat
-- Category page name
cat = 'Category:Articles that mention a specific rail gauge'
if show then
-- uses colon and wikilabel
cat = '[[:'.. cat .. '|Cat:Articles mentioning RailGauge]]'
end
return cat
end
-----------------------------------------------------------------------------------
-- prepareArgs -- Arguments coming from an #invoke or from a module
-----------------------------------------------------------------------------------
local function prepareArgs( frame )
-- If called via #invoke, use the args passed into the invoking
-- 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, make lower-case and remove blank arguments for all arguments
-- searchAlias is the cleaned value of [1]. [1] is kept as rawInput for error message
local args = {}
args["searchAlias"] = ''
args["rawInput"] = origArgs[ 1 ] or ''
for k, v in pairs( origArgs ) do
v = mw.text.trim( v )
if tonumber( k ) == nil then
-- Named argment
args[ k ] = mw.ustring.lower( v )
else
-- Unnamed argument, alias to be searched
-- Into lowercase, remove all whitespace, commas to create the search key
v = mw.ustring.lower( mw.ustring.gsub( v, '[%s%,]', '' ) )
args[ k ] = v
if k == 1 then
args["searchAlias"] = v
end
end
end
return args
end
-----------------------------------------------------------------------------------
-- maintReportArgs -- debug feedback, convenience.
-----------------------------------------------------------------------------------
local function maintReportArgs()
local args = prepareArgs( frame )
local report = 'args: '
for k, v in pairs( args ) do
report = report .. k .. '='.. v .. '; '
end
return '<tt>' .. report .. '</tt><br>'
end
-----------------------------------------------------------------------------------
-- getGaugeDataSet -- Find entry data for a single gauge
-----------------------------------------------------------------------------------
local function getGaugeDataSet( searchAlias )
if gaugeDataAll == nil then
gaugeDataAll = mw.loadData( dataPageName )
end
local rgEntry = nil
for i, rgEntry in ipairs( gaugeDataAll ) do
for j, alias in ipairs( rgEntry.aliases ) do
if alias == searchAlias then
return rgEntry
end
end
end
end
-----------------------------------------------------------------------------------
-- noWrap -- Add span tags to prevent a string from wrapping.
-----------------------------------------------------------------------------------
local function noWrap( s )
return mw.ustring.format( '<span class="nowrap">%s</span>', s )
end
-----------------------------------------------------------------------------------
-- frac -- A slimmed-down version of the {{frac}} template ( a nowrap to be added with the unit )
-----------------------------------------------------------------------------------
local function frac( whole, num, den )
return mw.ustring.format(
'<span class="frac">%s%s<sup>%s</sup>⁄<sub>%s</sub></span>',
whole or '', whole and '<span class="visualhide"> </span>' or '', num, den
)
end
-----------------------------------------------------------------------------------
-- formatImp -- Formats imperial units size into a single text element
-----------------------------------------------------------------------------------
local function formatImp( rgData, ulink, articleLink, pageName )
local ret = {}
local ft = rgData.ft
if ft then
local ftlink = ulink and not articleLink and '[[Foot (unit)|ft]]' or 'ft'
table.insert( ret, mw.ustring.format( '%s %s', ft, ftlink ) )
end
local inches = rgData['in']
local num = rgData.num
local den = rgData.den
if inches and not num and not den then
table.insert( ret, inches )
elseif num and den then
table.insert( ret, frac( inches, num, den ) )
end
if inches or num and den then
local incheslink = ulink and not articleLink and '[[inch|in]]' or 'in'
table.insert( ret, incheslink )
end
local gaugeSize = noWrap( table.concat( ret, ' ' ) )
if articleLink then
return '[[' .. pageName .. '|' .. gaugeSize .. ']]'
else
return gaugeSize
end
end
-----------------------------------------------------------------------------------
-- formatMet -- Formats metric measurements into a single formatted element
-----------------------------------------------------------------------------------
local function formatMet( rgData, ulink, articleLink, pageName )
local m = rgData.m
local gaugeSize
if m then
local munit = ulink and not articleLink and '[[metre|m]]' or 'm'
gaugeSize = noWrap( mw.ustring.format( '%s %s', m, munit ) )
else
local mm = rgData.mm
mm = tonumber( mm )
if mm then
mm = mw.getContentLanguage():formatNum( mm )
end
local mmunit = ulink and not articleLink and '[[millimetre|mm]]' or 'mm'
gaugeSize = noWrap( mw.ustring.format( '%s %s', mm, mmunit ) )
end
if articleLink then
return '[[' .. pageName .. '|' .. gaugeSize .. ']]'
else
return gaugeSize
end
end
-----------------------------------------------------------------------------------
-- compose -- Puts together the two metric, imperial measures into an output string.
-----------------------------------------------------------------------------------
local function compose( args, rgData )
local definition = rgData.def1
local pageName = rgData.pagename or nil
local imp = formatImp( rgData, args.unitlink == 'on',
args.lk=='on' and definition=='imp' and pageName, pageName )
local met = formatMet( rgData, args.unitlink == 'on',
args.lk=='on' and definition=='met' and pageName, pageName )
local first = args.first or rgData.def1
if first == 'met' or first == 'metric' then
first = 'met'
else
first = 'imp'
end
local ret = {}
if first == 'met' then
table.insert( ret, met )
else
table.insert( ret, imp )
end
local disp = args.disp
if disp ~= '1' then
local formatText
if disp == 's' or disp == '/' then
formatText = '/​%s'
elseif disp == 'or' then
formatText = ' or %s'
elseif disp == '=' then
formatText = ' = %s'
else
formatText = ' (%s)'
end
if first == 'met' then
table.insert( ret, mw.ustring.format( formatText, imp ) )
else
table.insert( ret, mw.ustring.format( formatText, met ) )
end
end
ret = table.concat( ret )
if args.wrap == 'y' then
return ret
else
return noWrap( ret )
end
end
-----------------------------------------------------------------------------------
-- main -- MAIN: the basic module
-----------------------------------------------------------------------------------
function p.main( frame )
local args = nil
local rgData = nil
local title = mw.title.getCurrentTitle()
args = prepareArgs( frame )
-- Get the data entry for this gauge from /data subpage
rgData = getGaugeDataSet( args.searchAlias )
-- Categorise the page if no gauge information was found.
if rgData == nil then
local category = ''
if title:inNamespaces( 0, 14 ) then --main=0, cat=14
category = mw.ustring.format(
'[[Category:Articles with template RailGauge with unrecognized input|%s, %s]]',
args["rawInput"] or ' ', title.text
)
end
return ( args["rawInput"] or '' ) .. category
end
local catMentions = ''
if rgData.id == '1435' then
-- no s.g. categorization
else
local addMentionsCat = args.addcat or 'yes'
if addMentionsCat ~= 'no' then
if title:inNamespaces( 0, 14 ) then
catMentions = catMentionsGaugeSize( rgData.id )
end
end
end
-- Assemble the output.
local ret = {}
table.insert( ret, compose( args, rgData ) )
local gaugeName = rgData.name
local gaugeLink = rgData.link
if args.allk == 'on' and gaugeLink then
table.insert( ret, ' ' .. noWrap( gaugeLink ) )
elseif args.al == 'on' and gaugeName then
table.insert( ret, ' ' .. noWrap( gaugeName ) )
end
table.insert( ret, catMentions )
return table.concat( ret )
end
-----------------------------------------------------------------------------------
-- checkData -- Public. Performs various checks on the /data subpage.
-----------------------------------------------------------------------------------
function p.checkData( frame )
local dataPage = frame and frame.args and frame.args[1] or dataPageName
local data = mw.loadData( dataPage )
local exists, dupes, dupeSort, ret = {}, {}, {}, {}
-- Check for duplicate aliases.
for ti, t in ipairs( data ) do
for ai, alias in ipairs( t.aliases or {} ) do
if not exists[ alias ] then
exists[ alias ] = { ti, ai }
else
if not dupes[ alias ] then
dupes[ alias ] = { exists[ alias ] }
end
table.insert( dupes[ alias ], { ti, ai } )
end
end
end
for alias in pairs( dupes ) do
table.insert( dupeSort, alias )
end
table.sort( dupeSort )
for i1, alias in ipairs( dupeSort ) do
local positions = {}
for i2, aliasKeys in ipairs( dupes[ alias ] ) do
local position = mw.ustring.format( 'gauge %d, alias %d ( gauge id: <code>%s</code> )', aliasKeys[ 1 ], aliasKeys[ 2 ], data[ aliasKeys[ 1 ] ].id or '' )
table.insert( positions, position )
end
local aliasText = mw.ustring.format( 'Duplicate aliases "%s" detected at the following positions: %s.', alias, mw.text.listToText( positions, '; ' ) )
table.insert( ret, aliasText )
end
-- Check for numerators without denominators.
for ti, t in ipairs( data ) do
local num = t.num
local den = t.den
if num and not den then
table.insert( ret, mw.ustring.format( 'Numerator "%s" with no denominator detected at gauge %d ( id: <code>%s</code> ).', num, ti, t.id or '' ) )
elseif den and not num then
table.insert( ret, mw.ustring.format( 'Denominator "%s" with no numerator detected at gauge %d ( id: <code>%s</code> ).', den, ti, t.id or '' ) )
end
end
-- Check for gauges with no imperial or no metric measurements.
for ti, t in ipairs( data ) do
if not ( t.ft or t['in'] or t.num or t.den ) then
table.insert( ret, mw.ustring.format( 'No imperial measurements found for gauge %d ( id: <code>%s</code> ).', ti, t.id or '' ) )
end
if not ( t.m or t.mm ) then
table.insert( ret, mw.ustring.format( 'No metric measurements found for gauge %d ( id: <code>%s</code> ).', ti, t.id or '' ) )
end
end
-- Check for non-numeric measurements.
local measurements = { 'ft', 'in', 'num', 'den', 'm', 'mm' }
for ti, t in ipairs( data ) do
for mi, measurement in ipairs( measurements ) do
local measurementVal = t[ measurement ]
if measurementVal and not tonumber( measurementVal ) then
table.insert( ret, mw.ustring.format( 'Non-numeric <code>%s</code> measurement ( "%s" ) found for gauge %d ( id: <code>%s</code> ).', measurement, measurementVal, ti, t.id or '' ) )
end
end
end
-- Check for gauges with no id.
for ti, t in ipairs( data ) do
if not t.id then
local aliases = {}
for i, alias in ipairs( t.aliases ) do
table.insert( aliases, mw.ustring.format( '<code>%s</code>', alias ) )
end
aliases = mw.ustring.format( ' ( aliases: %s )', mw.text.listToText( aliases ) )
table.insert( ret, mw.ustring.format( 'No id found for gauge %d%s.', ti, aliases or '' ) )
end
end
-- Check for gauges with no aliases.
for ti, t in ipairs( data ) do
if type( t.aliases ) ~= 'table' then
table.insert( ret, mw.ustring.format( 'No aliases found for gauge %d ( id: <code>%s</code> ).', ti, t.id or '' ) )
else
local isAlias = false
for ai, alias in ipairs( t.aliases ) do
isAlias = true
break
end
if not isAlias then
table.insert( ret, mw.ustring.format( 'No aliases found for gauge %d ( id: <code>%s</code> ).', ti, t.id or '' ) )
end
end
end
-- Check for named gauges with no links and gauges with links but no names.
for ti, t in ipairs( data ) do
if t.name and not t.link then
table.insert( ret, mw.ustring.format( 'No link found for the named gauge "%s" at position %d ( id: <code>%s</code> ).', t.name, ti, t.id or '' ) )
elseif t.link and not t.name then
table.insert( ret, mw.ustring.format( 'No name found for the gauge with link "%s" at position %d ( id: <code>%s</code> ).', t.link, ti, t.id or '' ) )
end
end
-- Check for invalid def1 values.
for ti, t in ipairs( data ) do
local def = t.def1
if def ~= 'imp' and def ~= 'met' then
table.insert( ret, mw.ustring.format( 'Invalid def1 value "%s" found for gauge %d ( id: <code>%s</code> ).', def or '', ti, t.id or '' ) )
end
end
-- Check for unwanted whitespace.
for ti, t in ipairs( data ) do
for tkey, tval in pairs( t ) do
if tkey == 'aliases' and type( tval ) == 'table' then
for ai, alias in ipairs( tval ) do
if mw.ustring.find( alias, '%s' ) then
table.insert( ret, mw.ustring.format( 'Unwanted whitespace detected in gauge %d alias %d ( "%s", gauge id: <code>%s</code> ).', ti, ai, alias, t.id or '' ) )
end
end
elseif tkey == 'name' or tkey == 'link' or tkey == 'pagename' or tkey == 'contentcat' then
if tval ~= mw.text.trim( tval ) then
table.insert( ret, mw.ustring.format( 'Unwanted whitespace detected in <code>%s</code> field of gauge %d ( "%s", gauge id: <code>%s</code> ).', tkey, ti, tval, t.id or '' ) )
end
elseif mw.ustring.find( tval, '%s' ) then
table.insert( ret, mw.ustring.format( 'Unwanted whitespace detected in <code>%s</code> field of gauge %d ( "%s", gauge id: <code>%s</code> ).', tkey, ti, tval, t.id or '' ) )
end
end
end
-- Added April 2014: alias should not double with another id ( imp and mm not ambiguous )
local self_id = ''
local self_def = ''
for ti, t in ipairs( data ) do
self_id = t.id
self_def = t.def1
for iC, aliasCheck in ipairs( t.aliases ) do
if tonumber( aliasCheck ) ~= nil then
if self_id ~= aliasCheck then
for iTwo, tTwo in ipairs( data ) do
if aliasCheck == tTwo.id then
table.insert( ret, mw.ustring.format( 'Input alias %s ( %s ) from <code>id=%s mm</code> ambiguous with gauge id=<code>%s mm</code> ( %s )', aliasCheck, self_def, self_id, tTwo.id, tTwo.def1 ) )
end
end
end
end
end
end
-- Return any errors found.
for i, msg in ipairs( ret ) do
ret[ i ] = mw.ustring.format( '<span class="error">%s</span>', msg )
end
if #ret > 0 then
return mw.ustring.format( 'Found the following errors in %s:\n* %s', dataPageName, table.concat( ret, '\n* ' ) )
else
return mw.ustring.format( 'No errors found in %s.', dataPageName )
end
end
-----------------------------------------------------------------------------------
-- documentHeader
-----------------------------------------------------------------------------------
local function documentHeader( numberOfEntries, docTitle, docState )
if docTitle == '' then
if ( numberOfEntries or 0 ) <= 1 then
docTitle = 'Rail gauge'
else
docTitle = 'Rail gauges'
end
end
if docState == '' then
docState = 'collapsible uncollapsed'
else
docState = 'collapsible ' .. docState
end
local sortColHeaders = ''
local sortClass = ''
if ( numberOfEntries or 0 ) > 1 then
sortClass = 'sortable'
sortColHeaders = '' ..
'\n|- ' ..
'\n! style="line-height:90%;" | || || || || || || ||'
end
-- 8 columns
local catMparent = catMentionsGaugeSizeParent( false )
return '' ..
'\n{| class="wikitable ' .. sortClass .. ' ' .. docState .. '" '
.. 'style="text-align:right; width:100%;" ' ..
'\n|+ style="background:#d8d8d8;" | ' .. docTitle ..
'\n|-' ..
'\n!'
.. ' style="background:#d8d8d8;" | Size<br>(mm)' --1
.. '\n! style="background:#d8d8d8;" | Size<br>(ft, in)' --2
.. '\n! style="background:#d8d8d8;" | Size<br>(inches)' --3
.. '\n! style="background:#d8d8d8;" | Units<br> ' --4
.. '\n! style="background:#d8d8d8; width:6em;" | Aliases<br>(input options)' --5
.. '\n! style="background:#d8d8d8; min-width:8em;" | Link<br> ' --6
.. '\n! style="background:#d8d8d8;" | [[:Category:Track gauges by size|Category]]<br>(content)' --7
.. '\n! style="background:#d8d8d8;" | [[:' .. catMparent .. '|Mentionings]]<br>(maintenance)'
.. sortColHeaders
end
-----------------------------------------------------------------------------------
-- documentFooter
-----------------------------------------------------------------------------------
local function documentFooter()
return '\n|}' .. '\n'
end
-----------------------------------------------------------------------------------
-- createcatMentionsGaugeSize -- Create and use preload. Not used after initial creation.
-----------------------------------------------------------------------------------
function createCatMentionsGaugeSize( id )
local preloadUrl = 'action=edit&preload=Template:RailGauge/preload-categorypage-railgauge-mentionings'
local catM = catMentionsGaugeSize( id, nil, nil, nil, true )
local qryString = mw.uri.parseQueryString( preloadUrl )
return tostring( mw.uri.fullUrl( catM, qryString ) )
end
-----------------------------------------------------------------------------------
-- fromInputToId -- Used cleaned Alias as searchkey
-----------------------------------------------------------------------------------
local function fromInputToId( searchAlias )
if gaugeDataAll == nil then
gaugeDataAll = mw.loadData( dataPageName )
end
for i, rgEntry in ipairs( gaugeDataAll ) do
for j, alias in ipairs( rgEntry.aliases ) do
if alias == searchAlias then
return rgEntry.id
end
end
end
-- Second search: by id
if tonumber( searchAlias ) ~= nil then
for i, rgEntry in ipairs( gaugeDataAll ) do
if rgEntry.id == searchAlias then
return rgEntry.id
end
end
end
end
-----------------------------------------------------------------------------------
-- documentInchCount -- Gives the number of inches in decimals.
-----------------------------------------------------------------------------------
local function documentInchCount( rgEntry )
local inches = 0
if rgEntry["num"] ~= nil then
inches = tonumber( ( rgEntry["num"] or 0 ) / ( rgEntry["den"] or 1 ) )
end
inches = tostring( inches + ( tonumber( rgEntry["ft"] or 0 ) * 12 )
+ tonumber( rgEntry["in"] or 0 ) )
return inches
end
-----------------------------------------------------------------------------------
-- documentInchToMm -- Not used lately
-----------------------------------------------------------------------------------
local function documentInchToMm( inchCount )
return tonumber( inchCount or 0 ) * 25.4
end
-----------------------------------------------------------------------------------
-- fromIdToEntrySet
-- From one id, make the set withall one-two-three-more entries ( met, inp, variants )
-----------------------------------------------------------------------------------
local function fromIdToEntrySet( id, searchedAlias )
local TableTools = require( 'Module:TableTools' )
local html = require( 'Module:HtmlBuilder' )
local htmlString = ''
local rowSplit = '<div style="border-top:1px solid #ccc; height:1px;"/>'
-- From the id, build the set of existing entries ( met, imp, and variants )
local entry = {}
local defType = 0
for i, rgEntry in ipairs( gaugeDataAll ) do
if id == rgEntry.id then
if rgEntry.def1 == 'met' and entry[ 1 ] == nil then
entry[ 1 ] = rgEntry
defType = defType +1
elseif rgEntry.def1 == 'imp' and entry[ 2 ] == nil then
entry[ 2 ] = rgEntry
defType = defType + 2
else
entry[ 3 + TableTools.size( entry ) ] = rgEntry
end
end
end
entry = TableTools.compressSparseArray( entry )
-- Entry set is now complete & clean
-- Result: the entry table with entries present in data,
-- In sequence if present ( 1. met, 2. imp, any extra )
if entry[ 1 ] == nil then
-- A non-existent id is entered? Unexpected here.
return '' ..
'\n|-' ..
'\n| colspan=7 style="color:red; text-align:left;" |' ..
'Error using [[Template:RailGauge/document gauge|RailGauge/document gauge]]:' ..
' No rail gauge defined for: "' .. ( searchedAlias or '' ) .. '"'
end
-- Build row from data ( all entries )
-- String together various data elements per cell
local inchCount = documentInchCount( entry[ 1 ] )
-- sortKey
local sortKey = formatUnitPlaintext( entry[ 1 ], 'met', 5 )
htmlString = html.create()
.tag( 'span' ).addClass( 'sortkey' ).wikitext( sortKey )
sortKey = tostring( htmlString )
-- aliases -- listing the input options
local aliasList = {}
for i, e in ipairs( entry ) do
local alis = {}
for j, v in ipairs( e.aliases ) do
if tonumber( v ) == nil then -- No plain numbers
table.insert( alis, tostring( v ) )
end
end
-- cannot sort aliases here ( ? )
for j, v in ipairs( alis ) do
if string.match( v, '^%d' ) == nil then -- textual so to italic. Todo: better uc
local txt = v
htmlString = html.create()
.tag( 'span' ).wikitext( txt ).css( 'font-style', 'italic' )
alis[ j ] = tostring( htmlString )
end
end
table.insert ( aliasList, table.concat( alis, '; ' ) )
end
-- def -- Definition unit ( def1 in data )
local def = {} -- definition code ( 'met' or 'imp' )
local defText = {}
for i, v in ipairs ( entry ) do
table.insert( def, v.def1 )
if v.def1 == 'imp' then
table.insert( defText, 'imperial' )
else
table.insert( defText, 'metric' )
end
end
-- mm; ft in -- Measurement ( number & unit; met and imp; anchor to here )
local measure = {}
local unitanchor = { '', '' }
measure[ 1 ] = formatMet( entry[ 1 ] )
measure[ 2 ] = formatImp( entry[ 1 ] ) -- both met and imp from entry[ 1 ]
if math.fmod( defType, 2 ) == 1 then
htmlString = html.create()
.tag( 'span' ).wikitext( measure[ 1 ] ).css( 'font-weight', 'bold' )
measure[ 1 ] = tostring( htmlString )
unitanchor[ 1 ] = anchor( entry[ 1 ], 'met' )
end
if defType >= 2 then
htmlString = html.create()
.tag( 'span' ).wikitext( measure[ 2 ] ).css( 'font-weight', 'bold' )
measure[ 2 ] = tostring( htmlString )
unitanchor[ 2 ] = anchor( entry[ 1 ], 'imp' )
end
-- Linked page
local linkPage = {}
for i, e in ipairs( entry ) do
table.insert( linkPage, e.pagename )
end
if #linkPage == 2 then
if linkPage[ 1 ] == linkPage[ 2 ] then
linkPage[ 2 ] = nil
end
end
for i, lp in ipairs( linkPage ) do
local fmtLp = ''
if string.len( lp ) > 15 then
fmtLp = '[[' .. lp .. ']]'
else
htmlString = html.create()
.tag( 'span' ).wikitext( lp ).addClass( 'nowrap' )
htmlString = tostring( htmlString )
fmtLp = '[[' .. lp .. '|' .. htmlString .. ']]'
end
htmlString = html.create()
.tag( 'span' ).css( 'text-align', 'left' ).wikitext( fmtLp )
linkPage[ i ] = tostring( htmlString )
end
-- catContent -- This is a possible category with content (not maintenance)
-- can be hardcoded in the data, or test by size pattern
local catContent = {}
local catTtl
local label
local catCsuffix = ' gauge railways'
for i, e in ipairs( entry ) do
if e.contentcat ~= nil then
label = string.match( e.contentcat, '([%S]*)' ) or 'nomatch'
table.insert( catContent,
'[[:Category:' .. e.contentcat .. '|cat:' .. label .. ']]' )
end
end
if #catContent == 0 then
if math.fmod( defType, 2 ) == 1 then
label = formatUnitPlaintext( entry[ 1 ], 'met' )
catTtl = mw.title.makeTitle( 14, label .. catCsuffix )
if catTtl.exists then
table.insert( catContent,
'[[:' .. catTtl.fullText .. '|cat:' .. noWrap( label ) .. ']]' )
end
end
if defType >= 2 then
label = formatUnitPlaintext( entry[ 1 ], 'imp', nil, true )
catTtl = mw.title.makeTitle( 14, label .. catCsuffix )
if catTtl.exists then
table.insert( catContent,
'[[:' .. catTtl.fullText .. '|cat:' .. noWrap( label ) .. ']]' )
end
end
end
-- Mentions category
local catMentions = catMentionsGaugeSize( id, catSort, title, true )
htmlString = html.create()
.tag( 'span' ).css( 'text-align', 'left' ).wikitext( catMentions )
catMentions = tostring( htmlString )
-- Create this cat (temporal, initial only)
local testTitle = mw.title.getCurrentTitle()
local createCat = ''
if testTitle.namespace == 2 then
createCat = '[' .. createCatMentionsGaugeSize( id ) .. ' c]'
end
-- Compose the id-row with all cell values
local row = {}
table.insert( row, sortKey .. unitanchor[ 1 ] .. measure[ 1 ] ) --1 met
table.insert( row, sortKey .. unitanchor[ 2 ] .. measure[ 2 ] ) --2 imp
table.insert( row, sortKey .. inchCount ) --3
table.insert( row, table.concat( defText, rowSplit ) ) --4
table.insert( row, table.concat( aliasList, rowSplit ) ) --5
table.insert( row, table.concat( linkPage, rowSplit ) ) --6
table.insert( row, table.concat( catContent, rowSplit ) ) --7
table.insert( row, catMentions ) --8
return '' ..
'\n|- style="background:#e8e8e8; border-top:2px solid #aaa;" | ' ..
'\n|' .. table.concat( row, ' || ' )
end
-----------------------------------------------------------------------------------
-- documentGauge -- Selfdocument gauge data ( one, multiple, range, all )
-----------------------------------------------------------------------------------
function p.documentGauge( frame )
local TableTools = require( 'Module:TableTools' )
local args = prepareArgs( frame )
gaugeDataAll = mw.loadData( dataPageName )
-- Series from the list
-- idFrom and idTo are numerical
local rgList = {}
local idFrom = -1
local idTo = -1
for i, v in ipairs( args ) do
if v == 'all' then
idFrom = -math.huge
idTo = math.huge
break
end
end
if args.docfrom ~= nil then
idFrom = tonumber( fromInputToId( args.docfrom )
or mw.ustring.gsub( '0' .. args.docfrom, 'mm', '' ) )
idTo = math.huge
end
if args.docto ~= nil then
idTo = tonumber( fromInputToId( args.docto )
or mw.ustring.gsub( '0' .. args.docto, 'mm', '' ) )
end
if idTo > 0 then -- some list is requested from the whole data set
if idFrom > idTo then
local dummy = idFrom
idFrom = idTo
idTo = dummy
end
for i, rgEntry in ipairs( gaugeDataAll ) do
if ( tonumber( rgEntry.id ) >= idFrom )
and ( tonumber( rgEntry.id ) <= idTo ) then
table.insert( rgList, tonumber( rgEntry.id ) )
end
end
rgList = TableTools.removeDuplicates( rgList )
table.sort( rgList )
end
-- Individual entries can be mentioned in args ( all unnamed = numbered params )
-- Need a straight table to keep sequence right
local argsAliases = TableTools.compressSparseArray( args )
for i, argsAlias in ipairs( argsAliases ) do
id = fromInputToId( argsAlias )
if id ~= nil then
-- Add to the top
table.insert( rgList, i, tonumber( id ) )
end
end
-- Now loop through the prepared rgList[id] and add rows to result table
-- One row contains all available entries for the id ( met, imp, a third variant )
local rowRGid = {}
for i, numId in ipairs( rgList ) do
table.insert( rowRGid, fromIdToEntrySet( tostring( numId ) ) )
end
return documentHeader( #rgList, args.doctitle or '', args.docstate or '' ) ..
table.concat( rowRGid, '' ) .. documentFooter()
end
-----------------------------------------------------------------------------------
-- gaugeSizeFromTitle
-- Currently finds "1620 mm" when at end of title, then returns "1620". Blank when not found.
-- Used for cat:mentions category page.
-----------------------------------------------------------------------------------
function p.gaugeSizeFromTitle()
local title = mw.title.getCurrentTitle()
return string.match( title.text, '%s(%d+%.?%d*)%smm$' ) or ''
end
-----------------------------------------------------------------------------------
-- catSortFromTitle
-- Currently finds "600 mm" when at end of title, then returns "0600 mm" (for catSort).
-- Blank when not found. Used for cat:mentions category page.
-----------------------------------------------------------------------------------
function p.catSortFromTitle()
local title = mw.title.getCurrentTitle()
local catSort = string.match( title.text, '%s(%d+%.?%d*)%smm$' ) or ''
if catSort ~= '' then
catSort = string.rep( '0',
4 - string.len( math.floor( tonumber( catSort ) ) ) )
.. catSort .. ' mm'
end
if catSort == '' then
return '*'
else
return catSort
end
end
--docNumAlias
function p.numAlias()
local ret = {}
local cat = ''
local idS = ''
gaugeDataAll = mw.loadData( dataPageName )
local rgEntry = nil
for i, rgEntry in ipairs( gaugeDataAll ) do
for j, alias in ipairs( rgEntry.aliases ) do
if tonumber(alias) == nil then
else
cat = 'Articles that mention rail gauge size' .. ' ' .. rgEntry.id .. ' mm'
table.insert( ret, rgEntry.id .. ' || ' .. mw.site.stats.pagesInCategory( cat ) .. ' || ' .. alias .. ' || [[:category:' .. cat .. ']] ||' )
end
end
end
table.sort(ret)
return '\n\n|-\n\n| ' .. table.concat(ret, '\n\n|-\n\n| ') .. '\n|}\n\n' ..#ret
end
return p