Mô đun:GHS phrases

  1. ^ a b “Globally Harmonized System of Classification and Labelling of Chemicals” (pdf). 2021. Annex 3: Codification of Statements and Pictograms (pp 268–385).
--------------------------------------------------------------------------------
-- 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]], [[Thể loại:Lỗi GHS]] (mainspace pages only)
--
-- Also: 
-- listAll(), numberOfPhrases(), listOmitRules(),
-- listtype, omit
--------------------------------------------------------------------------------
require('strict')
local r = {}	-- "r" for return, so no confusion with setID P
local GHSdata	= mw.loadData('Module:GHS phrases/data')
local getArgs	= require('Module:Arguments').getArgs
local 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 end
	
	if (sLabel or '') == '' then
		sLabel = ''
	else
		sLabel = '|' .. sLabel 
	end
	if (sSection or '') == '' then
		sSection = ''
	else
		sSection = '#' .. sSection
	end
	return '[[' .. 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').main
	
	local wlErrCat = ''
	if pagetype() == 'article' then -- mainspace only
		if sCatsort == nil then sCatsort = tArgName['setID'] end
		
		if sCatsort == '' then
			wlErrCat = '[[Thể loại:Lỗi GHS]]'
		else
			wlErrCat = '[[Thể loại:Lỗi GHS|' .. sCatsort .. ']]'
		end
	else
		return ''
	end

	table.insert(tMessagesToShow, wlErrCat)
	return
end

--------------------------------------------------------------------------------
-- addWarningCategory
--
-- Formats as [[Thể loại:Lỗi GHS|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').main
if sCatsort == nil then sCatsort = tArgName['setID'] end
		
	local wlWarnCat = ''
	if pagetype() == 'article' then -- mainspace only
		if sCatsort == '' then
			wlWarnCat = '[[Thể loại:Lỗi GHS]]'
		else
			wlWarnCat = '[[Thể loại:Lỗi GHS|' .. sCatsort .. ']]'
		end
	else
		return 
	end

	table.insert(tMessagesToShow, wlWarnCat)
	return
end

--------------------------------------------------------------------------------
-- addPreviewMsg
--------------------------------------------------------------------------------
local function addPreviewMsg(sMsg)
local previewWarn = require('Module:If preview')._warning
	table.insert(tMessagesToShow, previewWarn({sMsg}))
	return
end

--------------------------------------------------------------------------------
-- showPreviewMsg
--
-- show table tMessagesToShow
-- preview-messages and errorcat
-- all namespaces
--------------------------------------------------------------------------------
local function showPreviewMsg()
	if tTools.size(tMessagesToShow) > 0 then
		return table.concat(tMessagesToShow, '')
	else
		return ''
	end
end

--------------------------------------------------------------------------------
-- 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 = killer
local hit = false

	iR = 1
	while iR < #tArgs do
		iK = #tArgs -- will be counting downwards
		while iK > iR do
			if tArgs[iK] == tArgs[iR] then
				hit = true
				addPreviewMsg('Duplicate removed: ' .. tArgs[iR])
				table.remove(tArgs, iK)
				tTools.compressSparseArray(tArgs)
			end
			iK = iK - 1
		end
		tTools.compressSparseArray(tArgs)
		iR = iR + 1
	end

	if hit then
		addWarningCategory('D')
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- 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 = false
	
	for keep, omit in pairs(tRules) do
		if tTools.inArray(tArgs, omit) then
			if tTools.inArray(tArgs, keep) then
				hit = true
				for i, k in pairs(tArgs) do
					if k == omit then
						table.remove(tArgs, i)		
					end
				end
				addPreviewMsg(wlHelpPage('Omit Rules') .. ': keep ' .. keep .. ', omit ' .. omit)
			end
		end
	end
	if hit then
		tTools.compressSparseArray(tArgs)
		addWarningCategory('O')
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- label H-phrases or P-phrases
--------------------------------------------------------------------------------
local function PHlabel()
	if tArgName['setID'] == 'GHS' then
		return 'GHS phrases'
	else
		return tArgName['setID'] .. '-phrases'
	end
end

--------------------------------------------------------------------------------
-- inMono
--
-- Use mono font-family (from: Template:Mono)
--------------------------------------------------------------------------------
local function inMono(s)
	if s == nil then s = '' end
	return '<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 sMsg
	sMsg = '<sup><span class="noprint Inline-Template">&#91;<i>'
				.. wlHelpPage(PHlabel(), '<span title="' 
									.. PHlabel() .. ': '
									.. 'không tìm thấy '
									.. phraseID
									.. '">?</span>')
				.. '</i>&#93;</span></sup>'
	return sMsg
end

--------------------------------------------------------------------------------
-- 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 = '' end
	
	local inlineTag = wlInlineTag(phraseID)
	local previewMsg = wlHelpPage(PHlabel()) .. ': không tìm thấy \"' .. phraseID .. '\"'
	addPreviewMsg(previewMsg)
	addErrorCategory()
	
	return phraseID .. inlineTag
end

--------------------------------------------------------------------------------
-- errorHPsetIDnotFound
--
-- setID H or P could not be found
--------------------------------------------------------------------------------
local function errorHPsetIDnotFound()
	local sMsg
	sMsg = wlHelpPage('', PHlabel())
			.. ': không tìm thấy id "H" hoặc "P"' 
			.. ' (vui lòng sử dụng mẫu như "|H200" hoặc "|P300+P301")'
	addPreviewMsg(sMsg)
	addErrorCategory('?')
	return showPreviewMsg()
end

--------------------------------------------------------------------------------
-- errorHPsetIDmissing
--
-- parameter |setid= to be used
--------------------------------------------------------------------------------
local function errorHPsetIDmissing()
	local sMsg
	sMsg = wlHelpPage( '', PHlabel())
			.. ': không tìm thấy id "H" hoặc "P",' 
			.. ' vui lòng sử dụng |setid=... (H hoặc P)'
	addPreviewMsg(sMsg)
	return
end

--------------------------------------------------------------------------------
-- 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) .. ': ' .. sPhrase
end

--------------------------------------------------------------------------------
-- 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 nil
	
	if (paramsetID ~= nil) and (paramsetID == 'P' or paramsetID == 'H') then
		setIDfound = paramsetID
	else
		local initial = nil
		for i, v in ipairs(tArgs) do
			initial = mw.ustring.match(v, '^[PH]')
			if initial ~=nil then
				setIDfound = initial
				break
			end
		end
	end
	return setIDfound
end

--------------------------------------------------------------------------------
-- 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' then
		return 'abbr'
	elseif listTypes[sListType] == true then
		if sListType == 'horizontal ordered' then
			sListType = 'horizontal_ordered'
		end
		return sListType
	else 
		sListType = 'abbr'
	end
	return sListType
end

--------------------------------------------------------------------------------
-- getDoOmitRules
--------------------------------------------------------------------------------
local function getDoOmitRules(tArgs)
	local b = yesno(tArgs['omit'], true)
	
	if b == nil then b = true end

	return 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 args
	if string.len(tArgName['setID']) == 1 and #tArgs > 0 then
		for i, v in ipairs(tArgs) do
			v = 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] = v
		end
		table.sort(tArgs)
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- 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 tRead
	if tArgName['setID'] == 'H' then
		tRead = GHSdata['Hphrases']
	elseif tArgName['setID'] == 'P' then
		tRead = GHSdata['Pphrases']
	else 
		errorHPsetIDmissing()
		return  showPreviewMsg()
	end

	-- Intermediate table t2 to maintain order; read from original table (/data)
	local t2 = {}
	local iPh
	for s, v in pairs(tRead) do
		iPh = tonumber(mw.ustring.match(s, '[PH](%d%d%d)'))
		if string.len(s) > 4 then
			iPh = tTools.size(t2) + 1
		end
		table.insert(t2, iPh, s)
	end
	t2 = tTools.compressSparseArray(t2)
	table.sort(t2)

	local sTR, v, sAnchor
	-- i = array index, s = phraseID, v = phrase text
	for i, s in ipairs(t2) do
		v = tRead[s]
		sAnchor = '<span class="anchor" id="' .. s .. '"></span>'
		sTR = '|- ' .. sAnchor .. '\n| datasortvalue="' .. i .. '" | <span style="font-family: monospace;">' .. s .. '</span> || ' .. v
		table.insert(tL, sTR)
	end

	return 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 iT
	if tArgName['setID'] == 'H' then
		iT = tTools.size(GHSdata['Hphrases'])
	elseif tArgName['setID'] == 'P' then
		iT = tTools.size(GHSdata['Pphrases'])
	else
		errorHPsetIDmissing()
		return showPreviewMsg()
	end

	return 'GHS ' .. PHlabel() .. ' <span style="font-weight: normal;">(' .. tostring(iT) .. ')</span>'
end

--------------------------------------------------------------------------------
-- listOmitRules
--
-- self-documentation
--------------------------------------------------------------------------------
function r.listOmitRules()
local tRules = GHSdata['tOmitRules']
local tL = {}
local s

	s = 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) do
		s = '&bull; keep ' .. inMono(keep) .. ', omit ' .. inMono(omit)
		table.insert(tL, s)
	end
	return 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 then
		return showPreviewMsg() -- no content
	elseif tArgName['setID'] == 'GHS' then
		return errorHPsetIDnotFound()
	end

	tArgs = applyRemoveDuplicates(tArgs)
	if tArgName['omit'] then
		tArgs = applyOmitRules(tArgs)
	end

	local formatterF
	if tArgName['listtype'] == 'abbr' then
		formatterF = formatPhraseAbbr
	elseif tArgName['listtype'] == 'inline' then
		formatterF = formatPhraseInline
	else --- Module:List options
		formatterF = formatPhraseList
	end
	
	local tReadD = {}
	if tArgName['setID'] == 'H' then
		tReadD = GHSdata['Hphrases']
	elseif tArgName['setID'] == 'P' then
		tReadD = GHSdata['Pphrases']
	else
		return showPreviewMsg()
	end

	local sPhrase
	local tR = {}
	for i, v in ipairs(tArgs) do
		sPhrase = tReadD[v]
		if sPhrase == nil then
			table.insert(tR, errorPhraseIDnotFound(tostring(v)))
		else
			table.insert(tR, formatterF(v, sPhrase))
		end
	end

	if tArgName['listtype'] == 'abbr' then
		return table.concat(tR, ', ') .. showPreviewMsg()
	elseif tArgName['listtype'] == 'inline' then
		return table.concat(tR, ', ') .. showPreviewMsg()
	else
		local mList = require('Module:List')
		return mList[tArgName['listtype']](tR) .. showPreviewMsg()
	end
end

--------------------------------------------------------------------------------
-- 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) 
end


return r
Chúng tôi bán
Bài viết liên quan
Một xã hội thích nhắn tin hơn là gọi điện và nỗi cô đơn của xã hội hiện đại
Một xã hội thích nhắn tin hơn là gọi điện và nỗi cô đơn của xã hội hiện đại
Bạn có thể nhắn tin với rất nhiều người trên mạng xã hội nhưng với những người xung quanh bạn như gia đình, bạn bè lại trên thực tế lại nhận được rất ít những sự thấu hiểu thực sự của bạn
Những nhân vật Genshin Impact miễn phí sẽ phù hợp với đội hình như thế nào?
Những nhân vật Genshin Impact miễn phí sẽ phù hợp với đội hình như thế nào?
Cùng tìm hiểu cách xây dựng đội hình với các nhân vật miễn phí trong Genshin Impact
Spoiler Volume 19 LN: Rimuru nuốt chửng Michael
Spoiler Volume 19 LN: Rimuru nuốt chửng Michael
Rimuru đang dự hội nghị ở Ingrasia thì nghe tin chỗ Dagruel có biến nên xách theo Souei và Diablo chạy đến
Nhân vật Masumi Kamuro - Youkoso Jitsuryoku Shijou Shugi no Kyoushitsu e
Nhân vật Masumi Kamuro - Youkoso Jitsuryoku Shijou Shugi no Kyoushitsu e
Masumi Kamuro (神かむ室ろ 真ま澄すみ, Kamuro Masumi) là một học sinh của Lớp 1-A (Năm Nhất) và là thành viên của câu lạc bộ nghệ thuật. Cô là một người rất thật thà và trung thành, chưa hề làm gì gây tổn hại đến lớp mình.