Module:GHS phrases/sandbox

---------------------------------------------------------------------------------- Module:GHS phrases-- -- main: reads GHS parameters (arguments like "H301", "P401")--and returns for each (listtype='abbr'):--phraseID visible; formal phrase text as <abbr title="...">-- setID= "H" or "P"-- phraseID = e.g. "H201", "P231+P234"-- phrase text read from array tables in [[Module:GHS phrases/data]]---- Implements: [[Template:GHS phrases]]-- Helppage: [[Template:GHS phrases]]-- Error category: [[Category:GHS errors]], [[Category:GHS warnings]] (mainspace pages only)---- Also: -- listAll(), numberOfPhrases(), listOmitRules(),-- listtype, omit--------------------------------------------------------------------------------require('strict')local r = {}-- "r" for return, so no confusion with setID Plocal GHSdata= mw.loadData('Module:GHS phrases/data/sandbox')local getArgs= require('Module:Arguments').getArgslocal tTools= require('Module:TableTools')local yesno= require('Module:Yesno')local tArgName= {} -- named parameters (setid, omit, listtype)local tMessagesToShow = {} -- the tail: Preview, Categories---------------------------------------------------------------------------------- wlHelpPage---- Formats page as [[Helppage#Section|Label]]-- by default, sLabel == sSection--------------------------------------------------------------------------------local function wlHelpPage(sSection, sLabel)local sHelpPage = 'Template:GHS phrases'if sLabel == nil then sLabel = sSection endif (sLabel or '') == '' thensLabel = ''elsesLabel = '|' .. sLabel endif (sSection or '') == '' thensSection = ''elsesSection = '#' .. sSectionendreturn '[[' .. sHelpPage .. sSection .. sLabel .. ']]'end---------------------------------------------------------------------------------- addErrorCategory---- Formats as [[Category:GHS errors|catsort]]-- or '' when in other namespace.-- sCatsort option using: H, P, _--------------------------------------------------------------------------------local function addErrorCategory(sCatsort)local pagetype = require('Module:Pagetype').mainlocal wlErrCat = ''if pagetype() == 'article' then -- mainspace onlyif sCatsort == nil then sCatsort = tArgName['setID'] endif sCatsort == '' thenwlErrCat = '[[Category:GHS errors]]'elsewlErrCat = '[[Category:GHS errors|' .. sCatsort .. ']]'endelsereturn ''endtable.insert(tMessagesToShow, wlErrCat)returnend---------------------------------------------------------------------------------- addWarningCategory---- Formats as [[Category:GHS warnings|catsort]]-- mainspace only, or '' when in other namespace.-- sCatsort option using: H, P, U, ?, D, O--------------------------------------------------------------------------------local function addWarningCategory(sCatsort)local pagetype = require('Module:Pagetype').mainif sCatsort == nil then sCatsort = tArgName['setID'] endlocal wlWarnCat = ''if pagetype() == 'article' then -- mainspace onlyif sCatsort == '' thenwlWarnCat = '[[Category:GHS warnings]]'elsewlWarnCat = '[[Category:GHS warnings|' .. sCatsort .. ']]'endelsereturn endtable.insert(tMessagesToShow, wlWarnCat)returnend---------------------------------------------------------------------------------- addPreviewMsg--------------------------------------------------------------------------------local function addPreviewMsg(sMsg)local previewWarn = require('Module:If preview')._warningtable.insert(tMessagesToShow, previewWarn({sMsg}))returnend---------------------------------------------------------------------------------- showPreviewMsg---- show table tMessagesToShow-- preview-messages and errorcat-- all namespaces--------------------------------------------------------------------------------local function showPreviewMsg()if tTools.size(tMessagesToShow) > 0 thenreturn table.concat(tMessagesToShow, '')elsereturn ''endend---------------------------------------------------------------------------------- applyRemoveDuplicates---- returns edited table, with double Codes removed-- adds warning with codes.-- base table tArgs is walked through by a iwalker that reads a singel code,-- then a ikiller checks the upward part of the same table to delete all copies-- ikiller starts at end of table, walks towards iwalker; then tArgs is compressed-- iwalker steps 1 up in the freshly compressed table-- Used: iArgs is sorted, and order stays same. compress does not change that.--------------------------------------------------------------------------------local function applyRemoveDuplicates(tArgs)local iR, iK -- iR = reader, iK = killerlocal hit = falseiR = 1while iR < #tArgs doiK = #tArgs -- will be counting downwardswhile iK > iR doif tArgs[iK] == tArgs[iR] thenhit = trueaddPreviewMsg('Duplicate removed: ' .. tArgs[iR])table.remove(tArgs, iK)tTools.compressSparseArray(tArgs)endiK = iK - 1endtTools.compressSparseArray(tArgs)iR = iR + 1endif hit thenaddWarningCategory('D')endreturn tArgsend---------------------------------------------------------------------------------- applyOmitRules---- returns edited table, with Omit phraseID's removed-- Omit rule is per GHS_Rev9E_0.pdf (2021)--------------------------------------------------------------------------------local function applyOmitRules(tArgs)local tRules = GHSdata['tOmitRules']local hit = falsefor keep, omit in pairs(tRules) doif tTools.inArray(tArgs, omit) thenif tTools.inArray(tArgs, keep) thenhit = truefor i, k in pairs(tArgs) doif k == omit thentable.remove(tArgs, i)endendaddPreviewMsg(wlHelpPage('Omit Rules') .. ': keep ' .. keep .. ', omit ' .. omit)endendendif hit thentTools.compressSparseArray(tArgs)addWarningCategory('O')endreturn tArgsend---------------------------------------------------------------------------------- label H-phrases or P-phrases--------------------------------------------------------------------------------local function PHlabel()if tArgName['setID'] == 'GHS' thenreturn 'GHS phrases'elsereturn tArgName['setID'] .. '-phrases'endend---------------------------------------------------------------------------------- inMono---- Use mono font-family (from: Template:Mono)--------------------------------------------------------------------------------local function inMono(s)if s == nil then s = '' endreturn '<span class="monospaced" style="font-family: monospace;">' .. s .. '</span>'end---------------------------------------------------------------------------------- wlInlineTag---- Returns <sup>[?]</sup> with wikilink to [[helppage#section|errormessage]]--------------------------------------------------------------------------------local function wlInlineTag(phraseID)local sMsgsMsg = '<sup><span class="noprint Inline-Template">&#91;<i>'.. wlHelpPage(PHlabel(), '<span title="' .. PHlabel() .. ': '.. phraseID.. ' not found'.. '">?</span>').. '</i>&#93;</span></sup>'return sMsgend---------------------------------------------------------------------------------- errorPhraseIDnotFound---- Returns single value when error (not found in list):-- plain value + inline warning [?] (linked) + error cat (mainsp) + preview warning--------------------------------------------------------------------------------local function errorPhraseIDnotFound(phraseID)if phraseID == nil then phraseID = '' endlocal inlineTag = wlInlineTag(phraseID)local previewMsg = wlHelpPage(PHlabel()) .. ': \"' .. phraseID .. '\" not found'addPreviewMsg(previewMsg)addErrorCategory()return phraseID .. inlineTagend---------------------------------------------------------------------------------- errorHPsetIDnotFound---- setID H or P could not be found--------------------------------------------------------------------------------local function errorHPsetIDnotFound()local sMsgsMsg = wlHelpPage('', PHlabel()).. ': "H" or "P" set id not found' .. ' (please use form like "|H200" or "|P300+P301")'addPreviewMsg(sMsg)addErrorCategory('?')return showPreviewMsg()end---------------------------------------------------------------------------------- errorHPsetIDmissing---- parameter |setid= to be used--------------------------------------------------------------------------------local function errorHPsetIDmissing()local sMsgsMsg = wlHelpPage( '', PHlabel()).. ': "H" or "P" set id not found,' .. ' please use |setid=... (H or P)'addPreviewMsg(sMsg)returnend---------------------------------------------------------------------------------- formatPhraseAbbr---- format phraseID and text, for abbr-form (infobox list form)--------------------------------------------------------------------------------local function formatPhraseAbbr(phraseID, sPhrase)return '<abbr class="abbr" title=" ' .. phraseID .. ': ' .. sPhrase .. '">'.. phraseID .. '</abbr>'end---------------------------------------------------------------------------------- formatPhraseInline---- format phraseID and text, for inline form (in sentence)-- adds "quotes"--------------------------------------------------------------------------------local function formatPhraseInline(phraseID, sPhrase)return inMono(phraseID) .. ': \"' .. sPhrase .. '\"'end---------------------------------------------------------------------------------- formatPhraseList---- as inline, but no "quotes" added.--------------------------------------------------------------------------------local function formatPhraseList(phraseID, sPhrase)return inMono(phraseID) .. ': ' .. sPhraseend---------------------------------------------------------------------------------- getSetID---- Determines setID (expected either 'H' or 'P')-- First route is: read |setid=-- When |setid= is not set, --it looks for a first parameter that has an H of P prefix (in |P201|P202|...)--when not found, 'GHS' is retured-- In one call, P and H numbers can *not* be mixed--so "|H201|P202|" will cause error "P202 not found" (... in H-list)--------------------------------------------------------------------------------local function getSetID(tArgs)local setIDfound = 'GHS'local paramsetID = tArgs['setid'] or nilif (paramsetID ~= nil) and (paramsetID == 'P' or paramsetID == 'H') thensetIDfound = paramsetIDelselocal initial = nilfor i, v in ipairs(tArgs) doinitial = mw.ustring.match(v, '^[PH]')if initial ~=nil thensetIDfound = initialbreakendendendreturn setIDfoundend---------------------------------------------------------------------------------- getListType---- Checks list format, including those from Module:List--------------------------------------------------------------------------------local function getListType(tArgs)local listTypes = {['abbr'] = true,['bulleted'] = true,['unbulleted'] = true,['horizontal'] = true,['ordered'] = true,['horizontal_ordered'] = true,['horizontal ordered'] = true,['inline'] = true}local sListType = tArgs['listtype'] or 'abbr'if sListType == '' or sListType == 'abbr' thenreturn 'abbr'elseif listTypes[sListType] == true thenif sListType == 'horizontal ordered' thensListType = 'horizontal_ordered'endreturn sListTypeelse sListType = 'abbr'endreturn sListTypeend---------------------------------------------------------------------------------- getDoOmitRules--------------------------------------------------------------------------------local function getDoOmitRules(tArgs)local b = yesno(tArgs['omit'], true)if b == nil then b = true endreturn yesno(b, true)end---------------------------------------------------------------------------------- prepareArgs---- First: determine setID (from |setID= OR from prefixes in parameters)-- Then: clean up & format phrase IDs (=unnamed parameters)--remove bad characters, create H/P pattern "H201", "P310+P302"-- straight array, no nil's, sorted--------------------------------------------------------------------------------local function prepareArgs(tArgs)tArgName['setID'] = getSetID(tArgs)tArgName['listtype'] = getListType(tArgs)tArgName['omit'] = getDoOmitRules(tArgs)tArgs = tTools.compressSparseArray(tArgs) -- removes all named argsif string.len(tArgName['setID']) == 1 and #tArgs > 0 thenfor i, v in ipairs(tArgs) dov = mw.text.decode(v)v = mw.ustring.gsub(v, '[^%d%+A-Za-z]', '')v = mw.ustring.gsub(v, '^(%d)', tArgName['setID'] .. '%1')v = mw.ustring.gsub(v, '%+(%d)', '+' .. tArgName['setID'] .. '%1')tArgs[i] = vendtable.sort(tArgs)endreturn tArgsend---------------------------------------------------------------------------------- listAll---- Returns wikitable rows for each phrase id.-- requires |setID=P/H-- returns full list, all phrases, for a setID-- 2-columns wikitable, sorted, sortable, anchor like "H201" for each--------------------------------------------------------------------------------function r.listAll(frame)local newArgs = getArgs(frame)local tL = {}prepareArgs(newArgs)local tReadif tArgName['setID'] == 'H' thentRead = GHSdata['Hphrases']elseif tArgName['setID'] == 'P' thentRead = GHSdata['Pphrases']else errorHPsetIDmissing()return  showPreviewMsg()end-- Intermediate table t2 to maintain order; read from original table (/data)local t2 = {}local iPhfor s, v in pairs(tRead) doiPh = tonumber(mw.ustring.match(s, '[PH](%d%d%d)'))if string.len(s) > 4 theniPh = tTools.size(t2) + 1endtable.insert(t2, iPh, s)endt2 = tTools.compressSparseArray(t2)table.sort(t2)local sTR, v, sAnchor-- i = array index, s = phraseID, v = phrase textfor i, s in ipairs(t2) dov = tRead[s]sAnchor = '<span class="anchor" id="' .. s .. '"></span>'sTR = '|- ' .. sAnchor .. '\n| datasortvalue="' .. i .. '" | <span style="font-family: monospace;">' .. s .. '</span> || ' .. vtable.insert(tL, sTR)endreturn table.concat(tL, '\n')end---------------------------------------------------------------------------------- numberOfPhrases---- Documentation-- requires |setID=H/P-- Returns number of phrases, in format--"GHS H-phrases (123)"--------------------------------------------------------------------------------function r.numberOfPhrases(frame)local newArgs = getArgs(frame)prepareArgs(newArgs)local iTif tArgName['setID'] == 'H' theniT = tTools.size(GHSdata['Hphrases'])elseif tArgName['setID'] == 'P' theniT = tTools.size(GHSdata['Pphrases'])elseerrorHPsetIDmissing()return showPreviewMsg()endreturn 'GHS ' .. PHlabel() .. ' <span style="font-weight: normal;">(' .. tostring(iT) .. ')</span>'end---------------------------------------------------------------------------------- listOmitRules---- self-documentation--------------------------------------------------------------------------------function r.listOmitRules()local tRules = GHSdata['tOmitRules']local tL = {}local ss = wlHelpPage('Omit Rules').. ': when the <i>keep</i> ID is present, do not show the <i>omit</i> ID phrase'table.insert(tL, s)for keep, omit in pairs (tRules) dos = '&bull; keep ' .. inMono(keep) .. ', omit ' .. inMono(omit)table.insert(tL, s)endreturn table.concat(tL, '<br/>')end---------------------------------------------------------------------------------- _main---- processes setID (H, P) and phrase codes--error:setID not P, H--code not found-- cannot mix H and P phrases-- reads phrases from /data H or P phrases tables-- formats phrase (abbreviation, abbr-title, phraseID)--------------------------------------------------------------------------------function r._main(tArgs)tArgs = prepareArgs(tArgs)if #tArgs == 0 thenreturn showPreviewMsg() -- no contentelseif tArgName['setID'] == 'GHS' thenreturn errorHPsetIDnotFound()endtArgs = applyRemoveDuplicates(tArgs)if tArgName['omit'] thentArgs = applyOmitRules(tArgs)endlocal formatterFif tArgName['listtype'] == 'abbr' thenformatterF = formatPhraseAbbrelseif tArgName['listtype'] == 'inline' thenformatterF = formatPhraseInlineelse --- Module:List optionsformatterF = formatPhraseListendlocal tReadD = {}if tArgName['setID'] == 'H' thentReadD = GHSdata['Hphrases']elseif tArgName['setID'] == 'P' thentReadD = GHSdata['Pphrases']elsereturn showPreviewMsg()endlocal sPhraselocal tR = {}for i, v in ipairs(tArgs) dosPhrase = tReadD[v]if sPhrase == nil thentable.insert(tR, errorPhraseIDnotFound(tostring(v)))elsetable.insert(tR, formatterF(v, sPhrase))endendif tArgName['listtype'] == 'abbr' thenreturn table.concat(tR, ', ') .. showPreviewMsg()elseif tArgName['listtype'] == 'inline' thenreturn table.concat(tR, ', ') .. showPreviewMsg()elselocal mList = require('Module:List')return mList[tArgName['listtype']](tR) .. showPreviewMsg()endend---------------------------------------------------------------------------------- main---- handles template input frame, then calls generic _main() function-- To be invoked from {{template}}--------------------------------------------------------------------------------function r.main(frame)local newArgs = getArgs(frame)return r._main(newArgs) endreturn r