Documentation for this module may be created at Module:TagQS/doc

--[[  
   _____             .___    .__              ___________              ________    _________
  /     \   ____   __| _/_ __|  |   ____   /\ \__    ___/____     ____ \_____  \  /   _____/
 /  \ /  \ /  _ \ / __ |  |  \  | _/ __ \  \/   |    |  \__  \   / ___\ /  / \  \ \_____  \ 
/    Y    (  <_> ) /_/ |  |  /  |_\  ___/  /\   |    |   / __ \_/ /_/  >   \_/.  \/        \
\____|__  /\____/\____ |____/|____/\___  > \/   |____|  (____  /\___  /\_____\ \_/_______  /
        \/            \/               \/                    \//_____/        \__>       \/ 

                                                                             
This module is intended for creating invisible tags which can be used to pass 
language independent data from some templates to infoboxes. Those tags are often 
used by templates like [Template:Artwork]  to pass data to Wikidata

Authors and maintainers:
* User:Jarekt - original version 
]]

require('Module:No globals') -- used for debugging purposes as it detects cases of unintended global variables

-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}

function p.replaceUnlessQuoted(str, oldChar, newChar)
	local quote = string.byte('"')
	local comma = string.byte(oldChar)
	local quoted = false
	for pos = 1, #str do
	   if str:byte(pos) == quote then
		  quoted = not quoted
	   end
	   if str:byte(pos) == comma and not quoted then
		  str = str:sub(1,pos-1) .. newChar .. str:sub(pos+1, str:len())
	   end
	end
	return str
end

-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================
function p.createTag(field, property, value)
	return mw.ustring.format('<div style="display: none;">%s QS:%s,%s</div>\n', field, property or 'P', value)
end

function p.changeField(text, old, new)
	local patrn = '%<div style="display: none;"%>'.. old ..' QS:([^%<]+)%</div%>'
	local repl  = '<div style="display: none;">'.. new ..' QS:%1</div>'
	return mw.ustring.gsub(text, patrn, repl)
end

function p.changeProperty(text, field, old, new)
	if not old then
		old = '[^%,]+'
	end
	local patrn = '%<div style="display: none;"%>' .. field .. ' QS:' .. old .. ',([^%<]+)%</div%>'
	local repl  =   '<div style="display: none;">' .. field .. ' QS:' .. new .. ',%1</div>'
	return mw.ustring.gsub(text, patrn, repl)
end

function p.readTag(text, field)
	-- read a single tag
	local pat = '%<div style="display: none;"%>'..field..' QS:([^%<]+)%</div%>'
	local qs  = string.match(text, pat) -- find hidden tag with QS code
	local _, nMatch = string.gsub(text, pat, "") -- count matches
	if qs and nMatch==1 then -- allow only single matches
		return p.replaceUnlessQuoted(qs, ',', '|')
	end
end

function p.readTags(text, field)
	-- read a single tag
	local pat = '%<div style="display: none;"%>'..field..' QS:([^%<]+)%</div%>'
	local ret = {}
	for qs in mw.ustring.gmatch(text, pat) do
		table.insert(ret, p.replaceUnlessQuoted(qs, ',', '|') )
	end
	return ret
end

function p.hasTag(text, field)
	return text~= p.removeTag(text, field)
end

function p.removeTag(text, field)
	if not field then
		field = '[^ ]+'
	end
	local patrn = '%<div style="display: none;"%>' .. field .. ' QS:[^%<]+%</div%>'
	return mw.ustring.gsub(text, patrn, '')
end

-- ===========================================================================
-- === Versions of the function to be called from template namespace
-- ===========================================================================
function p.CreateTag(frame)
	return p.createTag(frame.args[1], frame.args[2], frame.args[3])
end

return p