Модуль:TagQS

    Матеріал з Релігія в огні

    Документацію для цього модуля можна створити у Модуль:TagQS/документація

    --[[  
       _____             .___    .__              ___________              ________    _________
      /     \   ____   __| _/_ __|  |   ____   /\ \__    ___/____     ____ \_____  \  /   _____/
     /  \ /  \ /  _ \ / __ |  |  \  | _/ __ \  \/   |    |  \__  \   / ___\ /  / \  \ \_____  \ 
    /    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('strict') -- used for debugging purposes as it detects cases of unintended global variables
    
    -- ==================================================
    -- === External functions ===========================
    -- ==================================================
    local p = {}
    
    function p.replaceUnlessQuoted(str, oldChar, newChar)
    	-- String "str" has some sections that are in quotes and some that are not. 
    	-- Do replacements only in the text sections which are not in "" quotes.
    	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)
    	-- create tags to insert using "field" "property" and "value" strings.
    	-- "field" is an unique label to distinguish it from other tags. 
    	-- "property" and "value" are actually in a format similar to the one expected by QuickStatements
    	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)
    	-- replace "field" part of the tag. It is needed as sometimes template adding those tags does not 
    	-- know the meaning, which is known the the outside template. For example in 
    	-- "{{Book|translator={{Creator|wikidata=Q12345}}" the Creator template will create initial 
    	-- tag with the wikidata item and {{Book}} template will add label and property for "transaltor".
    	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)
    	-- replace "property" part of the tag. It is needed as sometimes template adding those tags does not 
    	-- know the meaning, which is known the the outside template. For example in 
    	-- "{{Book|translator={{Creator|wikidata=Q12345}}" the Creator template will create initial 
    	-- tag with the wikidata item and {{Book}} template will add label and property for "transaltor".
    	if not old then -- string "old" is optional if nil than any property will be replaced
    		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 multiple tags and return array of them
    	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)
    	-- does the "text" has a tag with field "field", or if field=nil does it have any tags?
    	return text~= p.removeTag(text, field)
    end
    
    function p.removeTag(text, field)
    	-- remove tags with field "field" from the string. Field =nil will replace all tags
    	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