Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Special pages
Cultopedia
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Module:Check height
Module
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- Validates height formatting in infoboxes and adds error tracking categories when issues are found local p = {} -- Default ranges local DEFAULT_FT_MIN = 4.10 local DEFAULT_FT_MAX = 6.11 local DEFAULT_CM_MIN = 147 local DEFAULT_CM_MAX = 212 -- Helper function to parse and validate ftin_range parameter local function parseFtInRange(rangeStr) if not rangeStr or rangeStr == '' then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end -- Pattern: number (with optional decimal) - number (with optional decimal) local minStr, maxStr = rangeStr:match('^(%d+%.%d+)%-(%d+%.%d+)$') if not minStr or not maxStr then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end local minVal = tonumber(minStr) local maxVal = tonumber(maxStr) if not minVal or not maxVal then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end -- Validate that decimal part is exactly 2 digits and represents inches (00-11) local minInches = minStr:match('%.(%d+)$') local maxInches = maxStr:match('%.(%d+)$') if not minInches or not maxInches then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end -- Check exactly 2 digits if #minInches ~= 2 or #maxInches ~= 2 then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end -- Check range 00-11 local minInchesNum = tonumber(minInches) local maxInchesNum = tonumber(maxInches) if not minInchesNum or not maxInchesNum or minInchesNum < 0 or minInchesNum > 11 or maxInchesNum < 0 or maxInchesNum > 11 then return DEFAULT_FT_MIN, DEFAULT_FT_MAX end return minVal, maxVal end -- Helper function to parse and validate cm_range parameter local function parseCmRange(rangeStr) if not rangeStr or rangeStr == '' then return DEFAULT_CM_MIN, DEFAULT_CM_MAX end -- Pattern: number - number (no decimals allowed) local minStr, maxStr = rangeStr:match('^(%d+)%-(%d+)$') if not minStr or not maxStr then return DEFAULT_CM_MIN, DEFAULT_CM_MAX end local minVal = tonumber(minStr) local maxVal = tonumber(maxStr) if not minVal or not maxVal then return DEFAULT_CM_MIN, DEFAULT_CM_MAX end return minVal, maxVal end -- Helper function to remove fraction HTML markup local function removeFractionMarkup(str) if not str then return str end -- Remove templatestyles strip marker str = str:gsub("\127'\"`UNIQ%-%-templatestyles.-QINU`\"'\127", '') -- Remove span tags with specific classes while preserving inner content appropriately -- For sr-only spans, we want to convert the + to actual + str = str:gsub('<span class="sr%-only">%+</span>', '+') -- Remove the frac wrapper span (keep contents) str = str:gsub('<span class="frac">(.-)</span>', '%1') -- Remove num spans (keep contents) str = str:gsub('<span class="num">(.-)</span>', '%1') -- Remove den spans (keep contents) str = str:gsub('<span class="den">(.-)</span>', '%1') return str end -- Helper function to remove references/inline tags local function removeReferences(str) if not str then return str end -- Pattern for MediaWiki strip markers (references) str = str:gsub("\127'\"`UNIQ%-%-ref.-QINU`\"'\127", '') -- Pattern for inline tags (e.g. citation needed) str = str:gsub('%[%[Category:.-%</sup>', '') return str end -- Helper function to extract regular and converted heights local function extractHeights(str) if not str then return nil, nil, false end local regular, converted = str:match('^(.-)%s%((.-)%)$') if not regular or not converted then return nil, nil, false end local reconstructed = str:gsub('^' .. regular:gsub('([%(%)%.%%%+%-%*%?%[%]%^%$])', '%%%1'), '') local expectedRemainder = ' (' .. converted .. ')' local actualRemainder = reconstructed local remainderCheck = actualRemainder:gsub(converted:gsub('([%(%)%.%%%+%-%*%?%[%]%^%$])', '%%%1'), '') if remainderCheck ~= ' ()' then return nil, nil, false end return regular, converted, true end -- Helper function to delink wikilinks local function delink(str) if not str then return str end return str:gsub("%[%[(.-)%]%]", function(match) local pipePos = match:find("|") if pipePos then return match:sub(pipePos + 1) else return match end end) end -- Helper function to check for invalid decimal feet/inches format (e.g., "5.5 ft" instead of "5 ft 6 in") local function hasDecimalImperial(str) if not str then return false end -- Delink the string and convert to lowercase local testStr = delink(str) local lowerStr = testStr:lower() -- Replace with regular space lowerStr = lowerStr:gsub(' ', ' ') -- Regex pattern if lowerStr:match('%d[,.]%d%s*foot') or lowerStr:match('%d[,.]%d%s*feet') or lowerStr:match('%d[,.]%d%s*ft') or lowerStr:match("%d%.%d+%s*[β²']") or lowerStr:match('%d[,.]%d%s*in') then return true end return false end -- Helper function to check for parentheses without inside them local function hasParenWithoutNbsp(str) if not str then return false end -- Remove references and inline tags str = removeReferences(str) -- Find all parenthetical expressions and check if any lack for parenContent in str:gmatch('%((.-)%)') do if not parenContent:find(' ') then return true end end return false end -- Validate imperial height format local function validateImperial(height, ftMin, ftMax) if not height then return false end -- Extract feet and inches parts from the min/max values local minFeet = math.floor(ftMin) local minInches = math.floor((ftMin - minFeet) * 100 + 0.5) local maxFeet = math.floor(ftMax) local maxInches = math.floor((ftMax - maxFeet) * 100 + 0.5) -- Pattern 1: X ft Y in (simple) local feet, inches = height:match('^(%d+) ft (%d+) in$') if feet and inches then feet = tonumber(feet) inches = tonumber(inches) -- Check if within range if feet < minFeet or feet > maxFeet then return false end if feet == minFeet and inches < minInches then return false end if feet == maxFeet and inches > maxInches then return false end if inches < 0 or inches > 11 then return false end return true end -- Pattern 2a: X ft Y+N⁄D in (whole inches plus fraction, e.g., "6 ft 2+1/2 in") local feet2, inches2, num2, den2 = height:match('^(%d+) ft (%d+)%+(%d+)⁄(%d+) in$') if feet2 and inches2 and num2 and den2 then feet2 = tonumber(feet2) inches2 = tonumber(inches2) num2 = tonumber(num2) den2 = tonumber(den2) -- Reject "0+" before fraction (should use pattern 2b instead) if inches2 == 0 then return false end -- Check if within range if feet2 < minFeet or feet2 > maxFeet then return false end if feet2 == minFeet and inches2 < minInches then return false end if feet2 == maxFeet and inches2 > maxInches then return false end if inches2 < 0 or inches2 > 11 then return false end -- Numerator must be at least 1, denominator must be > 1, and num < den if num2 < 1 or den2 <= 1 or num2 >= den2 then return false end return true end -- Pattern 2b: X ft N⁄D in (fraction only, e.g., "6 ft 1/2 in") local feet3, num3, den3 = height:match('^(%d+) ft (%d+)⁄(%d+) in$') if feet3 and num3 and den3 then feet3 = tonumber(feet3) num3 = tonumber(num3) den3 = tonumber(den3) -- Check if within range (inches = 0 for range checking purposes) if feet3 < minFeet or feet3 > maxFeet then return false end if feet3 == minFeet and 0 < minInches then return false end if feet3 == maxFeet and 0 > maxInches then return false end -- Numerator must be at least 1, denominator must be > 1, and num < den if num3 < 1 or den3 <= 1 or num3 >= den3 then return false end return true end return false end -- Validate metric height format (meters) local function validateMeters(height, cmMin, cmMax) if not height then return false end -- Pattern: X.XX m local meters = height:match('^(%d+%.%d+) m$') if meters then -- Remove decimal point and check value local metersNoDot = meters:gsub('%.', '') local numericValue = tonumber(metersNoDot) if numericValue and numericValue >= cmMin and numericValue <= cmMax then return true end end return false end -- Validate metric height format (centimeters) local function validateCentimeters(height, cmMin, cmMax) if not height then return false end -- Pattern: XXX cm local cm = height:match('^(%d+) cm$') if cm then local numericValue = tonumber(cm) if numericValue and numericValue >= cmMin and numericValue <= cmMax then return true end end return false end -- Validate metric height based on metric parameter local function validateMetric(height, metricParam, cmMin, cmMax) if not height then return false end metricParam = metricParam or 'both' if metricParam == 'm' then return validateMeters(height, cmMin, cmMax) elseif metricParam == 'cm' then return validateCentimeters(height, cmMin, cmMax) else -- 'both' or default return validateMeters(height, cmMin, cmMax) or validateCentimeters(height, cmMin, cmMax) end end -- Main function function p.main(frame) local arguments = require('Module:Arguments') local personHeight = require('Module:Person height') local args = arguments.getArgs(frame, {trim = true}) local parentArgs = frame:getParent().args -- Get parameters local height = args[1] or parentArgs[1] or '' local metricParam = args['metric'] or parentArgs['metric'] or 'both' local catParam = args['cat'] or parentArgs['cat'] or '' local ftinRangeParam = args['ftin_range'] or parentArgs['ftin_range'] or '' local cmRangeParam = args['cm_range'] or parentArgs['cm_range'] or '' -- Parse range parameters local ftMin, ftMax = parseFtInRange(ftinRangeParam) local cmMin, cmMax = parseCmRange(cmRangeParam) -- If no height provided, return empty if height == '' then return '' end -- Check raw input for invalid decimal feet format (e.g., "5.5 ft" instead of "5 ft 6 in") if hasDecimalImperial(height) then mw.addWarning('<span style="color:#d33">Height format error: The raw height input does not match the expected pattern (feet or inches value uses decimal).</span>') if catParam ~= '' then return '[[Category:' .. catParam .. ']]' end return '' end -- Check raw input for parentheses without inside if hasParenWithoutNbsp(height) then mw.addWarning('<span style="color:#d33">Height format error: The raw height input should not include the converted height in parentheses (this should be calculated automatically or by a template).</span>') if catParam ~= '' then return '[[Category:' .. catParam .. ']]' end return '' end -- Set enforce based on metric parameter (nil if 'both') local enforceValue = nil if metricParam == 'm' then enforceValue = 'm' elseif metricParam == 'cm' then enforceValue = 'cm' end local heightArgs = { [1] = height, ['enforce'] = enforceValue, ['ri'] = 'cmin' } -- Use pcall to catch any errors from Module:Person height local success, formattedHeight = pcall(function() return personHeight.main(frame:newChild{ args = heightArgs }) end) -- If Module:Person height produced an error, treat as invalid structure if not success then if catParam ~= '' then return '[[Category:' .. catParam .. ']]' end return '' end -- Remove fraction markup local cleanedHeight = removeFractionMarkup(formattedHeight) -- Trim any trailing whitespace cleanedHeight = cleanedHeight:gsub('%s+$', '') -- Remove references and inline tags cleanedHeight = removeReferences(cleanedHeight) -- Extract regular and converted heights local regularHeight, convertedHeight, structureValid = extractHeights(cleanedHeight) -- Check if structure is valid if not structureValid then -- Add error category mw.addWarning('<span style="color:#d33">Height format error: The height format does not match the expected pattern.</span>') if catParam ~= '' then return '[[Category:' .. catParam .. ']]' end return '' end -- Validate the heights local regularValid = false local convertedValid = false -- Check if regular height is imperial or metric if validateImperial(regularHeight, ftMin, ftMax) then regularValid = true -- If regular is imperial, converted should be metric convertedValid = validateMetric(convertedHeight, metricParam, cmMin, cmMax) elseif validateMetric(regularHeight, metricParam, cmMin, cmMax) then regularValid = true -- If regular is metric, converted should be imperial convertedValid = validateImperial(convertedHeight, ftMin, ftMax) end -- If validation failed, add error category if not regularValid or not convertedValid then if catParam ~= '' then -- Create dynamic error message based on current ranges local ftMinFeet = math.floor(ftMin) local ftMinInches = math.floor((ftMin - ftMinFeet) * 100 + 0.5) local ftMaxFeet = math.floor(ftMax) local ftMaxInches = math.floor((ftMax - ftMaxFeet) * 100 + 0.5) local errorMsg = string.format( '<span style="color:#d33">Height format error: The height values or format are not within acceptable ranges. Height must be between %d\'%d" and %d\'%d" (%dβ%d cm).</span>', ftMinFeet, ftMinInches, ftMaxFeet, ftMaxInches, cmMin, cmMax ) mw.addWarning(errorMsg) return '[[Category:' .. catParam .. ']]' end end -- All checks passed, return empty return '' end return p
Summary:
Please note that all contributions to Cultopedia may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Cultopedia:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Template used on this page:
Module:Check height/doc
(
edit
)
Search
Search
Editing
Module:Check height
Add topic