Modul:VCard

Aus Wikivoyage
Zur Navigation springen Zur Suche springen
Template-info.png Dokumentation für das Modul VCard[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]

Anmerkungen

Anwendung

Der Modul wird direkt von der Vorlage {{vCard}} aufgerufen. Parameterbeschreibung siehe dort.

Experimentalbeispiele

* {{vCard | name= Ein Hotel | type = hostel | url= http://hotel.de | lat = 52.5144 | long = 13.389722 | show = all, subtype | address = Hauptstraße 1 | directions = Abzweig von der Nebenstraße | description = Das in der Innenstadt gelegene Hotel besitzt großzügige Räume, bietet aber nur {{Abk|ÜF}}. | phone = +49 (0)30 2345 1234 | fax = +49 (0)30 2345 9876, +49 0176 345 1234 | before = {{flagicon|Deutschland}} | image = Berlin Friedrichstraße Galeries Lafayette.jpg | email = info@hotel.de | comment = j | lastedit = 2016-11-17 | hours = 7/24. | checkin = ab 14 Uhr | checkout = bis 12 Uhr | credit-cards = Visa, Master, AmEx, Maestro | subtype = wlan, bar, pool | skype = nutzer.name; nutzer2.name }}

* {{vCard | wikidata = Q201219 | auto = j | name = [[Kairo/Ägyptisches Museum|Ägyptisches Museum Kairo]] | comment = auch Nationalmuseum | alt = Egyptian Museum | name-latin = al-Matḥaf al-Miṣrī | address = Mīdān et-Taḥrīr | address-local = ميدان التحرير | directions = im Stadtzentrum | directions-local = بوسط البلد }}
* {{vCard | wikidata = Q1142142 | auto = j | name = Nordiska museet }} Noch weiterer Text.
* {{vCard | wikidata = Q1142142 | auto = j | price = n }}
* {{vCard | wikidata = Q257342 | auto = j }}
* {{vCard | wikidata = Q28934 | auto = j | description = Test Durchhangeln. }}
* {{vCard | wikidata = Q4872 | auto = j }}
* {{vCard | wikidata = Q10697 | auto = j }}
* {{vCard | wikidata = Q12508 | auto = j | description = Test Durchhangeln. }}
* {{vCard | wikidata = Q46033 | description = Test Flughafen. }}
* {{vCard | wikidata = Q13218762 | auto = j | description = Anzeige englische Wikipedia. }}
* {{vCard | wikidata = Q47429618 | auto = j | description = Ausgabe Anschriften. | show = subtype | credit-cards = Visa, Master }}
* {{vCard | wikidata = Q47429618 | address = | address-local = | directions = | phone = | description = Test WD-Ausgabe. }}
* {{vCard | wikidata = Q637739 | auto = j | show = subtype | description = Rollstuhl aus WD. }}
  • DeutschlandFlagge Deutschland 1 Ein Hotel, Hauptstraße 1 (Abzweig von der Nebenstraße). Tel.: +49 (0)30 2345 1234, Fax: +49 (0)30 2345 9876, +49 0176 345 1234, E-Mail: , Skype: nutzer.name, nutzer2.name. Das in der Innenstadt gelegene Hotel besitzt großzügige Räume, bietet aber nur ÜF. Geöffnet: 7/24. Check-in: ab 14 Uhr. Check-out: bis 12 Uhr. Merkmale: WLAN [bar] [pool]. (52° 30′ 52″ N 13° 23′ 23″ O)

Parameter show

  • Mögliche Werte: none, poi, coord, all, subtype, nosubtype, indent, inline. Eine kommaseparierte Liste mehrerer Werte ist möglich.
  • Man kann die Standardwerte überschreiben.
  • Darstellung von Marker und Koordinaten.
    • poi und coord sind stärker als all. none ist stärker als poi, coord und all.
  • Die Ausgabe der Subtypen ist vorbereitet, wird aber zurzeit nicht standardmäßig durchgeführt (nosubtype).
    • nosubtype ist stärker als subtype.
  • Block-/Inline-Darstellung
    • Zukünftig wird die vCard standardmäßig im Block-Modus (css: display = block) angezeigt werden. Gegenwärtig Inline-Modus aufgrund zahlreicher Verwendung in diesem Modus. Dies schließt Beschränkungen bei den Darstellungsmöglichkeiten der Beschreibung description ein. inline schaltet vom Block- in den Inline-Modus.
    • Zukünftig bewirkt indent im Blockmodus einen eingerückten Absatz mit hängender erster Zeile. Das POI-Symbol wirkt dann wie ein Aufzählungszeichen.
Hinweise
-- module import
local mb = require( 'Module:MarkerBase' )
local mi = require( 'Module:MarkerBase/i18n' )
local fw = require( 'Module:FastWikidata' )

local vp = require( 'Module:VCard/Params' ) -- parameter lists
local vi = require( 'Module:VCard/i18n' ) -- parameter translations
local vs = require( 'Module:VCard/Subtypes' ) -- features of a location
local vr = mw.loadData( 'Module:VCard/Cards') -- payment types
local vd = mw.loadData( 'Module:VCard/Defaults' ) -- country-specific show defaults
local vm = mw.loadData( 'Module:VCard/Currencies' ) -- additional currency symbols

local yn = require( 'Module:Yesno' )
local cm = require( 'Module:CountryData' )
local pt = mw.loadData( 'Module:Wikidata2/POITypes' ) -- WD types to vCard/Poi types
local lg = require( 'Module:Languages' )
local lp = require( 'Module:LinkPhone' )
local lm = require( 'Module:LinkMail' )
local ls = require( 'Module:LinkSkype' )
local un = require( 'Module:Unesco' )

-- module variable
local vc = {
	wdContent = {}
}

-- Splitting comma separated lists to an array
-- convert = true: conversion to lowercase characters, spaces to low lines
-- toValue = true: list items handled as array values
-- toValue = false: list items handled as array keys
function vc.split( s, convert, toValue )
	local i, t
	local arr = {}
	if not s or s == '' then return arr end

	local arr2 = mw.text.split( s, ',', true )
	for i = 1, #arr2, 1 do
		t = mw.text.trim( arr2[ i ] )
		if t ~= '' then
			if convert then t = string.gsub( t:lower(), ' ', '_' ) end
			if toValue then
				table.insert( arr, t )
			else
				arr[ t ] = ''
			end
		end
	end

	return arr
end

-- Splitting comma separated lists to an array of key items
-- checking items with allowed key values of validValues array
function vc.splitAndCheck( s, validValues )
	local arr = {}, k, v
	local err = ''
	if not s or s == '' or not validValues then
		return arr, err
	end

	arr = vc.split( s, true )
	for k, v in pairs( arr ) do -- error handling
		if not validValues[ k ] then
			if err ~= '' then err = err .. ', ' end
			err = err .. k
			v = nil
		end
	end
	return arr, err
end

-- p : property id
-- tp: data value type
-- mx: maximum count
-- f : format
function vc.getWDvalues( p, tp, mx, f, l, entity, wikiLang, clang )
	-- clang = country.lang
	local r = ''
	local a, i, t, u, w
	local ar = {} -- empty array
	if l == 'wiki' then
		ar = fw.getValuesByLang( entity, p, mx, wikiLang )
	elseif l == 'local' then
		ar = fw.getValuesByLang( entity, p, mx, clang )
	elseif ( l == true ) and ( mx == 1 ) then
		t = lg.getProperty( wikiLang, 'q' )
		u = lg.getProperty( clang, 'q' )
		a = fw.getValuesWithQualifierIds( entity, p, 'P407', u )
		if next( a ) then
			i = a[ t ] -- item in wikiLang
			if not i then
				i = a[ u ] -- item in country lang
				if not i then
					i = a[ next( a, nil ) ] -- first item
				end
			end
			ar = { i }
		end
	else
		ar = fw.getValues( entity, p, mx )
	end
	if #ar == 0 then return ar end

	if p == 'P31' then
		return { fw.typeSearch( ar, pt, mi.searchLimit ) }
	else
		for i = 1, #ar, 1 do
			if tp == '' or tp == 'il' then
				if (ar[i] ~= '') and (f ~= '') and f:find( '$1' ) then
					ar[i] = mw.ustring.gsub( f, '($1)', ar[i])
				end

			elseif tp == 'id' then
				ar[i] = ar[i].id
				if (ar[i] ~= '') and (f ~= '') and f:find( '$1' ) then
					ar[i] = mw.ustring.gsub( f, '($1)', ar[i])
				end

			elseif tp == 'au' then
				a = ar[i].amount
				a = mw.ustring.gsub( a, '+', '')
				if mi.texts.decimalPoint ~= '.' then
					a = mw.ustring.gsub( a, '%.', mi.texts.decimalPoint)
				end
				u = ar[i].unit
				u = mw.ustring.gsub( u, 'http://www.wikidata.org/entity/', '' )
				if mw.ustring.match( u, '^Q[%d]+$') then
					t = fw.getValue( u, 'P558' ) -- unit
					if t == '' then
						t = fw.getValue( u, 'P498' ) -- currency code
					end
					if t ~= '' then u = t end
				end
				if (a ~= '') and (u ~= '') then
					if (f ~= '') and f:find( '$1' ) and f:find( '$2' ) then
						a = mw.ustring.gsub( f, '($1)', a)
						a = mw.ustring.gsub( a, '($2)', u)
					else
						a = a .. ' ' .. u
					end
				else
					a = a .. ' ' .. u
				end
				if (a == '') or (a == ' ') then ar[i] = nil else ar[i] = a end
			end
		end
	end
	return ar
end

function vc.getFromWD( parWDitem, entity, wikiLang, clang )
	local arr = {} -- contains results of multiple singleProperty() calls

	local function singleProperty( pr, f, c, v, l )
		if #arr == 0 then
			arr = vc.getWDvalues( pr, v or '', c or 1, f or '', l, entity, wikiLang, clang )
		else
			local subArr = vc.getWDvalues( pr, v or '', c or 1, f or '', l, entity, wikiLang, clang )

			if #subArr > 0 then -- move to arr
				for i = 1, #subArr, 1 do table.insert( arr, subArr[i] ) end
			end
		end
	
		return
	end

	local p = parWDitem, i, prop
	if not p then return '' end
	p.c = p.c or 1 -- count

	if type( p.p ) == 'string' then
		prop = p.p
		singleProperty( p.p, p.f, p.c, p.v, p.l )
	elseif type( p.p ) == 'table' then
		for key, value in pairs( p.p ) do
			if type( value ) == 'table' then
				prop = value.p
				singleProperty( value.p, value.f, value.c, value.v, value.l )
			end
		end
	end

	if #arr > p.c then
		for i = p.c + 1, #arr, 1 do arr[i] = nil end
	end
	if #arr > 0 then
		if p.m then -- analyzing concat modes
			if p.m == 'no' then
				return arr
			else
				return table.concat( arr, p.m )
			end
		else
			return table.concat( arr, ', ' )
		end
	else
		return ''
	end
end

function vc.getAddressesFromWD( vcEntity, country, wikiLang )
	local addresses = {}, key, value, t, u, w, weight

	if vp.ParMap.auto then
		if vp.ParMap.address == '' then vp.ParMap.address = true end
		if vp.ParMap.addressLocal == '' then vp.ParMap.addressLocal = true end
	end

	-- getting addresses from Wikidata but only if necessary
	if vp.ParMap.wikidata ~= '' and
		( vp.ParMap.address == true or vp.ParMap.addressLocal == true ) then
		-- new address property P6375
		addresses = fw.getValuesWithLanguages( vcEntity, 'P6375' )
		if next( addresses ) then -- sometimes addresses contain <br> tag(s)
			for key, value in pairs( addresses ) do
				addresses[ key ] = mw.ustring.gsub( value, '<br%s*/*>', ' ' )
			end
		else
			addresses = nil
		end
	end

	if addresses and vp.ParMap.address == true then
		vp.ParMap.address = addresses[ wikiLang ]
		-- select address if the same writing system is used
		if not vp.ParMap.address then
			local weight = -1
			u = lg.getProperty( wikiLang, 'w' ) -- writing entity id
			for key, value in pairs( addresses ) do
				-- same writing entity id as wikilang
				if key and ( lg.getProperty( key, 'w' ) == u ) then
					w = lg.getProperty( key, 'c' ) -- checking language weight
					if w > weight then -- check language weight
						vp.ParMap.address = value
						vp.ParMap.addressLang = key
						weight = w
					end
				end
			end
		end
		if not vp.ParMap.address then
			vp.ParMap.address = addresses.en
			vp.ParMap.addressLang = 'en'
		end
		if not vp.ParMap.address then
			vp.ParMap.address = addresses.fr
			vp.ParMap.addressLang = 'fr'
		end
		if not vp.ParMap.address then
			vp.ParMap.address = ''
			vp.ParMap.addressLang = ''
		end
		if vp.ParMap.address ~= '' then vc.wdContent.address = true end
	elseif type( vp.ParMap.address ) == 'boolean' then
		vp.ParMap.address = ''
	end

	if addresses and ( vp.ParMap.addressLocal == true ) and
		( country.lang ~= wikiLang ) and ( country.lang ~= 'en' ) and
		( country.lang ~= 'fr' ) then
		if country.lang ~= '' then
			vp.ParMap.addressLocal = addresses[ country.lang ] or ''
		else
			-- unknown language, maybe missing in Module:Languages
			vp.ParMap.addressLocal = addresses.unknown or ''
		end
		if vp.ParMap.addressLocal ~= '' then vc.wdContent.addressLocal = true end
	elseif type( vp.ParMap.addressLocal ) == 'boolean' then
		vp.ParMap.addressLocal = ''
	end

	-- analysing addressLocal vs address
	if ( vp.ParMap.address == vp.ParMap.addressLocal ) or
		( vp.ParMap.addressLang and ( vp.ParMap.addressLang == country.lang ) ) then
		vp.ParMap.addressLocal = ''
	end
	if ( vp.ParMap.addressLocal ~= '' ) and ( vp.ParMap.address == '' ) then
		vp.ParMap.address =
			vc.languageSpan( vp.ParMap.addressLocal, mi.texts.hintAddress, wikiLang, country )
		vp.ParMap.addressLocal = ''
		vc.wdContent.address = vc.wdContent.addressLocal
	end
end

function vc.formatText( key, class )
	if vp.ParMap[key] == '' then return '' end
	
	local r = ' <span class="' .. class
	if vc.wdContent[key] then r = r .. ' wikidata-content' end
	r = r .. '">'
	if mi.texts[key] ~= '' then r = r .. mi.texts[key] .. ' ' end
	r = r .. vp.ParMap[key]
	if not vp.ParMap[key]:find( '%.$' ) then r = r .. '.' end
	return r .. '</span>'
end

function vc.formatPhone( key, country, text )
	if vp.ParMap[key] == '' then return text end
	if text ~= '' then text = text .. ', ' end
	
	local pArgs = {}
	pArgs.phone = vp.ParMap[key]
	pArgs.cc = country.cc
	pArgs.nocc = 'true'
	pArgs.isFax = ''
	pArgs.isTollfree = ''
	pArgs.format = ''
	local t = mi.texts[key]
	if key == 'fax' then
		t = t .. ' <span class="p-tel-fax fax listing-fax'
		pArgs.isFax = 'true'
	else
		t = t .. ' <span class="p-tel tel listing-phone'
		if key == 'phone' then t = t .. ' listing-landline'
		elseif key == 'tollfree' then t = t .. ' listing-tollfree'
			pArgs.isTollfree = 'true'
		elseif key == 'mobile' then t = t .. ' listing-mobile'
		end
	end
	if vc.wdContent[key] then
		t = t .. ' wikidata-content'
		pArgs.format = 'true'
		pArgs.size = country.phoneDigits or 2
	end
	t = t .. '">' .. lp.linkPhoneNumberSet( pArgs ) .. '</span>'
	return text .. t
end

function vc.formatSocial( key, f, url, name )
	local t = vp.ParMap[key], s
	if t == '' then return '' end
	if not t:find( f ) then t = url .. t end
	s = ' <span class="listing-social-media'
	if vc.wdContent[key] then s = s .. ' wikidata-content' end
	return s .. '">[' .. t .. string.format( mi.icons[key], name ) .. ']</span>'
end

-- bdi and bdo tags are not working properly on all browsers. Adding marks
-- (lrm, rlm) is maybe the only way for a correct output
function vc.languageSpan( s, titleHint, wikiLang, country )
	local c = country.lang
	if ( s or '' ) == '' then return '' end
	if (c == '') or (c == wikiLang) then return s end

	local isR2L = lg.isR2L( c )
	local t = '<span lang="' .. c .. '" xml:lang="' .. c .. '"' ..
		' title="' .. titleHint .. ' ' .. country.langName .. '"'
	if isR2L then
		t = t .. ' dir="rtl"'
	else
		if wikiLangR2L then t = t .. ' dir="ltr"' end
	end
	t = t .. '>' .. s .. '</span>'
	if isR2L and not wikiLangR2L then t = '&rlm;' .. t .. '&lrm;' end
	if not isR2L and wikiLangR2L then t = '&lrm;' .. t .. '&rlm;' end
	return t
end

function vc.formatDate( aDate, aFormat )
	return mw.getContentLanguage():formatDate( aFormat, aDate, true )
end

function vc.addSisterIcons( sisters, wikidata, name, id )
	local t = '', key, value
	for key, value in pairs( sisters ) do
		if value ~= '' then
			t = t .. ' <span class="listing-sister-icon listing-sister-' .. key .. '">['
				.. value .. ' ' .. string.format( mi.icons[key], name ) .. ']</span>'
		end
	end
	local s = ''
	if wikidata ~= '' then
		s = '<span class="listing-sister-icon listing-sister-wikidata">['
			.. tostring( mw.uri.fullUrl( 'd:' .. wikidata ) )
			.. ' ' .. string.format( mi.icons.wikidata, name, id ) .. ']</span>'
		t = t .. s
	end
	return t, s
end

-- vCard main function

function vc.vCard( frame )
	local wikiLang = mw.getContentLanguage():getCode()
	local wikiLangR2L = lg.isR2L( wikiLang )
	local vcEntity = nil -- location (vCard/listing) entity
	local wrongQualifier = false

	local r, s, t, u, key, value, key2, value2
	local errShow, arrShow, addShow, arrSubtype
	local cntrl = false

	local args = frame:getParent().args
	args[ vi.p.name ] = args[ vi.p.name ] or ''
	args[ vi.p.nameLocal ] = args[ vi.p.nameLocal ] or ''
	vp.ParMap.nameLocal = args[ vi.p.nameLocal ]

	local extra = 'type:landmark_globe:earth'
	local thisWiki = ''  -- current Wikivoyage branch
	local sisters = {
		wikivoyage = '', -- link to another branch, usually en, as a sister link
		commons    = '', -- link to Commons category
		wikipedia  = ''  -- link to Wikipedia
	}

	vp.ParMap.wikidata, vcEntity, wrongQualifier = fw.getEntity( args[ vi.p.wikidata ] or '' )
	if not args[ vi.p.auto ] then
		args[ vi.p.auto ] = 'n'
	elseif args[ vi.p.auto ] == '' then
		args[ vi.p.auto ] = 'y'
	end
	vp.ParMap.auto = yn( args[ vi.p.auto ], false )

	t = yn( args[ vi.p.name ], nil )
	if t ~= nil then args[ vi.p.name ] = '' end

	-- getting name from Wikidata
	if vp.ParMap.wikidata == '' then
		vp.ParMap.auto = false
	else
		if args[ vi.p.name ] == '' then
			if wikiLang == 'en' then
				args[ vi.p.name ] = vcEntity:getLabel() or ''
			else
				args[ vi.p.name ] = vcEntity:getLabel() or vcEntity:getLabel( 'en' ) or ''
			end
			vp.ParMap.name = args[ vi.p.name ]
			vc.wdContent.name = ''
		end
	end

	-- checking for expensive sites and countries and getting country-specific data

	-- Country-specific technical parameters
	local country = {
		id = '',
		iso_3166 = '',
		cc = '',
		lang = '',
		langName = '',
		currency = '',
		country = ''
	}

	country = cm.getCountryData( vcEntity )
	if country.iso_3166 ~= '' then
		extra = extra .. '_region:' .. country.iso_3166
		t = vd[country.iso_3166]
		if t then vp.ParMap.show = t end
	end
	if country.lang ~= '' then
		country.langName = lg.getProperty( country.lang, 'n' )
	end

	if (vp.ParMap.wikidata ~= '') and vcEntity.sitelinks then
		if vcEntity.sitelinks[wikiLang .. 'wikivoyage'] then
			thisWiki = vcEntity.sitelinks[wikiLang .. 'wikivoyage'].title
			if thisWiki == mw.title.getCurrentTitle().text then
				thisWiki = '' end -- no link to the article itself
		end
		if wikiLang == 'en' then
			sisters.wikipedia = mb.getWikiLink( {wikiLang, country.lang}, 'wiki', vcEntity )
		else
			sisters.wikipedia = mb.getWikiLink( {wikiLang, 'en', country.lang}, 'wiki', vcEntity )
		end
		if thisWiki == '' then
			if wikiLang == 'en' then
				sisters.wikivoyage = mb.getWikiLink( {country.lang}, 'wikivoyage', vcEntity )
			else
				sisters.wikivoyage = mb.getWikiLink( {'en', country.lang}, 'wikivoyage', vcEntity )
			end
		end
	end

	-- handling args and vp.ParMap show arrays
	arrShow = vc.split( vp.ParMap.show, true )
	addShow, errShow = vc.splitAndCheck( args[ vi.p.show ], vp.show )
	if addShow.none or addShow.coord or addShow.all
		then arrShow.poi = nil -- overwriting default
	end
	for key, value in pairs( addShow ) do arrShow[key] = value end
	if arrShow.none or arrShow.coord or arrShow.poi
		then arrShow.all = nil
	end
	if arrShow.none then
		arrShow.coord = nil
		arrShow.poi = nil
	end
	if arrShow.nosubtype then
		arrShow.subtype = nil	
	end
	if arrShow.subtype then 
		vp.ParMap.subtypeAdd = not args[ vi.p.subtypeAdd ]
	end

	-- force getting data from Wikidata if existent
	if vp.ParMap.auto == true then
		if ( args[ vi.p.nameLocal ] or '' ) == '' and (wikiLang ~= country.lang) then
			args[ vi.p.nameLocal ] = true
			vp.ParMap.nameLocal = true
		end
		for key, value in pairs( vp.ParWD ) do
			if vi.p[ key ] then
				if ( args[ vi.p[ key ] ] or '' ) == '' then
					args[ vi.p[ key ] ] = true
					vp.ParMap[ key ] = true
				end
			end
		end
	end

	-- copying args parameters to vp.ParMap parameters
	local errorMsgs = '', translKey
	local descrDiv = false -- description with div or span tag
	for key, value in pairs( args ) do
		translKey = nil
		for key2, value2 in pairs( vi.p ) do
			if value2 == key then
				translKey = key2
				break
			end
		end

		-- remove breaks and controls
		t = mw.ustring.gsub( value, '</br>', ' ' )
		if arrShow.inline or translKey ~= 'description' then
			t = mw.ustring.gsub( t, '<br%s*/*>', ' ' )
			t = mw.ustring.gsub( t, '<p>', ' ' )
			if not mw.ustring.find( t, '<span' ) then
				t = mw.ustring.gsub( t, '[%z\000-\031]', ' ' )
				-- not %c because \127 is used for Mediawiki tags (strip markers `UNIQ)
			end
		else
			t = mw.ustring.gsub( t, '[%z\000-\009\011\012\014-\031]', ' ' )
			descrDiv = t:find( '[\010\013]' ) or t:find( '<br%s*/*>' ) or t:find( '<p>' )
		end
		if t ~= value then
			cntrl = true
			value = t
		end

		if translKey then
			if (translKey ~= 'auto') and (translKey ~= 'show') and (translKey ~= 'wikidata') then
				if value == '' then
					value = true
				elseif not value then
					value = false
				end
				t = yn( value, nil )
				if t ~= nil then
					if vp.ParMap.wikidata ~= '' then
						vp.ParMap[ translKey ] = t
					else
						vp.ParMap[ translKey ] = ''
					end
				else
					vp.ParMap[ translKey ] = value
				end
			end
		else
			if errorMsgs == '' then
				errorMsgs = '' .. key -- converting numbers to string
			else
				errorMsgs = errorMsgs .. ', ' .. key
			end
		end
	end
	if errorMsgs ~= '' then
		if errorMsgs:find( ',' ) then
			t = mi.errorMsg.unknownParams
		else
			t = mi.errorMsg.unknownParam
		end
		errorMsgs = '<span class="error">' .. t .. errorMsgs .. mi.errorMsg.maintenance .. '</span>'
	end

	-- getting addresses from Wikidata
	vc.getAddressesFromWD( vcEntity, country, wikiLang )

	-- error handling
	if country.fromWD then errorMsgs = errorMsgs .. mi.errorMsg.countryFromWD end
	if addShow.inline then errorMsgs = errorMsgs .. mi.errorMsg.inlineSelected end

	-- image check
	if ( type( vp.ParMap.image ) ~= 'boolean' ) and ( vp.ParMap.image ~= '' ) then
		vp.ParMap.image, errorMsgs = mb.checkImage( vp.ParMap.image, errorMsgs, vcEntity )
	end

	-- handling linked names like [[article|text]]
	local name = mb.getName( vp.ParMap.name, thisWiki )

	-- getting data from Wikidata
	if vp.ParMap.wikidata ~= '' then
		for key, value in pairs( vp.ParMap ) do
			if (key ~= 'auto') and (key ~= 'show') and (key ~= 'wikidata')
				and (key ~= 'name') and (vp.ParMap[key] == true) then
				if key == 'nameLocal' then
					vp.ParMap.nameLocal = vcEntity:getLabel( country.lang ) or ''
					if mw.ustring.upper( vp.ParMap.nameLocal ) == mw.ustring.upper( name.name ) then
						vp.ParMap.nameLocal = ''
					end
					vc.wdContent.nameLocal = ''
				elseif vp.ParMap[key] and vp.ParWD[key] then
					vp.ParMap[key] = vc.getFromWD( vp.ParWD[key], vcEntity, wikiLang, country.lang )
					vc.wdContent[key] = ''
				else vp.ParMap[key] = '' end
			end
		end
		if vp.ParMap.type == '' then
			vp.ParMap.type = vc.getFromWD( vp.ParWD.type, vcEntity, country.lang ) end
	end
	for key, value in pairs( vp.ParMap ) do
		if type( vp.ParMap[key] ) == 'boolean' then vp.ParMap[key] = '' end		
	end

	-- use local name if name is not given
	if name.name == '' and vp.ParMap.nameLocal ~= '' then
		vp.ParMap.name = vp.ParMap.nameLocal
		name = mb.getName( vp.ParMap.name, thisWiki )
		vp.ParMap.nameLocal = ''
	end
	-- missing name
	if name.name == '' then 
		vp.ParMap.name = mi.errorMsg.missingName
		name = mb.getName( vp.ParMap.name, thisWiki )
		errorMsgs = errorMsgs .. mi.errorMsg.missingNameMsg
	end
	-- names shall not contain tags or template calls
	if vp.ParMap.name:find( '<' ) or vp.ParMap.name:find( '{{' ) or 
		vp.ParMap.nameLocal:find( '<' ) or vp.ParMap.nameLocal:find( '{{' ) then
		errorMsgs = errorMsgs .. mi.errorMsg.malformedName
	end

	-- error handling of subtype array
	arrSubtype, t = vc.splitAndCheck( vp.ParMap.subtype, vs.f )
	if t ~= '' then t = mi.errorMsg.unknownSubtype .. ' ' .. t end
	if errShow ~= '' then t = t .. mi.errorMsg.unknownShow .. ' ' .. errShow end
	if t ~= '' then
		errorMsgs = errorMsgs .. '<span class="error">' .. t  .. '</span>'
	end

	-- checking and getting coordinates
	local dms = false
	vp.ParMap.lat, vp.ParMap.long, dms = mb.checkCoordinates( vp.ParMap.lat, vp.ParMap.long )
	if dms then errorMsgs = errorMsgs .. mi.errorMsg.dmsCoordinate end
	if (vp.ParMap.lat == '') or (vp.ParMap.long == '') then
		if vp.ParMap.wikidata ~= '' then
			t = fw.getValue( vcEntity, 'P625' )
			if t ~= '' then
				vp.ParMap.lat = t.latitude
				vp.ParMap.long = t.longitude
				vc.wdContent.lat = ''
			end
		end
	end
	if (vp.ParMap.lat == '') or (vp.ParMap.long == '') then
		arrShow.all = nil
		arrShow.coord = nil
		arrShow.poi = nil
	end

	-- getting Marker type and group
	vp.ParMap.type, vp.ParMap.group, errorMsgs =
		mb.checkTypeAndGroup( vp.ParMap.type, vp.ParMap.group, errorMsgs )
	vp.ParMap.groupTranslated = mb.translateGroup( vp.ParMap.group )

	-- generating output
	-- leading part for marker mode: only location names and comment

	vp.ParMap.zoom = mi.defaultZoomLevel
	
	-- wrapping tag
	r = 'vCard vcard h-card'
	if arrShow.indent then r = r .. ' listing-indent' end
	if arrShow.inline then r = '<span class="' .. r .. '"'
		else r = '<div class="' .. r .. '"' end

	-- adding metadata to the wrapping tag
	r = r .. mb.data( 'data-region', country.iso_3166 )
		.. mb.data( 'data-country', country.country )
		.. mb.data( 'data-country-calling-code', country.cc )
		.. mb.data( 'data-lang', country.lang )
		.. mb.data( 'data-wikilang', wikiLang )
		.. mb.data( 'data-location', mb.htmlReplace( mw.title.getCurrentTitle().subpageText ) )
		.. mb.data( 'data-name', mb.htmlReplace( name.name ) )
		.. mb.data( 'data-symbol', '-number-' .. vp.ParMap.group )
	if country.currency ~= '' then
		r = r .. ' data-currency="' .. country.currency
		if vm[country.currency]
			then r = r .. ', ' .. vm[country.currency] end
		r = r .. '"'
	end
	for key, value in pairs( vi.vcardData ) do
		r = r .. mb.data( value, vp.ParMap[ key ] )
	end
	local color = mb.getColor( vp.ParMap.group )
	r = r .. mb.data( 'data-color', '#' .. color )
	if country.lang == '' then
		errorMsgs = errorMsgs .. mi.errorMsg.unknownLanguage
	end
	if vp.ParMap.commonscat ~= '' then
		errorMsgs = errorMsgs .. mi.errorMsg.commonscat
	end
	if vp.ParMap.wikidata ~= '' then
		r = r .. mb.data( 'data-wikidata', vp.ParMap.wikidata )
		t = fw.getValue( vcEntity, 'P373' )
		if (t ~= '') and (vp.ParMap.commonscat ~= '') then
			errorMsgs = errorMsgs .. mi.errorMsg.commonscatWD
		end
		if vp.ParMap.commonscat == '' then
			vp.ParMap.commonscat = t
		end
	end
	if vp.ParMap.commonscat ~= '' then
		t = mw.ustring.gsub( vp.ParMap.commonscat, ' ', '_' )
		r = r .. mb.data( 'data-commonscat', t )
		sisters.commons = tostring( mw.uri.fullUrl( 'c:Category:' .. mw.uri.encode( t, 'WIKI' ) ) )
	end
	r = r .. mb.data( 'data-url', mw.text.nowiki( vp.ParMap.url ) )
		.. mb.data( 'data-image', mw.ustring.gsub(  vp.ParMap.image, ' ', '_' ) )
		.. '>' -- tag closing

	-- inserting content

	if vp.ParMap.image ~= '' then
		r = r .. '<span class="listing-image" style="display: none">[[File:' .. vp.ParMap.image
			.. '|350px|class=noviewer|' .. name.all .. ']]</span>'
	end

	if (vp.ParMap.lat ~= '') and (vp.ParMap.long ~= '') then
		r = r .. '<span class="p-geo geo listing-coordinates" style="display: none">'
			.. '<span class="p-latitude latitude">' .. vp.ParMap.lat .. '</span>'
			.. '<span class="p-longitude longitude">' .. vp.ParMap.long .. '</span></span>'
			.. frame:callParserFunction{ name = '#coordinates',
			args = { vp.ParMap.lat, vp.ParMap.long, extra, name = name.name } }
	end
	if vp.ParMap.before ~= '' then r = r .. vp.ParMap.before .. '&#160;' end

	-- adding POI marker
	if arrShow.all or arrShow.poi then
		r = r ..
			mb.addingMarkerSymbol( vp.ParMap, name.all, '', '-number-' .. vp.ParMap.group,
				false, color, frame ) .. ' '
	end
	
	-- adding names, url, comment and airport codes
	if vc.wdContent.name then r = r .. '<span class="wikidata-content">' end
	r = r .. '<bdi id="vCard_' .. mw.uri.anchorEncode( name.name )
		.. '" class="p-name p-org fn org listing-name">'
	-- url check
	vp.ParMap.url, errorMsgs = mb.checkUrl( vp.ParMap.url, errorMsgs )
	if vp.ParMap.url ~= '' then
		if name.pageTitle == '' then
			r = r .. '[' .. vp.ParMap.url .. ' ' .. name.name .. ']'
			if vp.ParMap.nameExtra ~= '' then r = r .. ' ' .. vp.ParMap.nameExtra end
			r = r .. '</bdi>'
		else
			-- article and web links
			r = r .. name.all
			if vp.ParMap.nameExtra ~= '' then r = r .. ' ' .. vp.ParMap.nameExtra end
			r = r .. '</bdi> <span class="listing-url">['
				.. vp.ParMap.url .. ' ' .. mi.icons.internet .. ']</span>'
		end
	else
		r = r .. name.all
		if vp.ParMap.nameExtra ~= '' then r = r .. ' ' .. vp.ParMap.nameExtra end
		r = r .. '</bdi>'
	end
	if vc.wdContent.name then r = r .. '</span>' end

	t = ''
	if mi.options.showLocalData then
		if vp.ParMap.nameLocal ~= '' then
			t = vc.languageSpan( vp.ParMap.nameLocal, mi.texts.hintName, wikiLang, country )
			if vc.wdContent.nameLocal then
				t = '<span class="listing-name-local wikidata-content">' .. t .. '</span>'
			else
				t = '<span class="listing-name-local">' .. t .. '</span>'
			end
		end
		if vp.ParMap.nameLatin ~= '' then
			if t ~= '' then t = t .. ', ' end
			t = t .. '<span class="listing-name-latin listing-emphasized" title="' .. mi.texts.hintLatin .. '">'
				.. vp.ParMap.nameLatin .. '</span>'
		end
	end
	if vp.ParMap.alt ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. '<bdi>' .. vp.ParMap.alt .. '</bdi>'
	end
	if t ~= '' then
		t = '<span class="p-nickname nickname listing-alt">' .. t .. '</span>'
	end
	if vp.ParMap.comment ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. '<span class="listing-comment listing-emphasized"><bdi>' .. vp.ParMap.comment .. '</bdi></span>'
	end
	if vp.ParMap.iata ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. mi.texts.iataLink .. ': ' .. vp.ParMap.iata
	end
	if (vp.ParMap.iata == '') and (vp.ParMap.icao ~= '') then
		if t ~= '' then t = t .. ', ' end
		t = t .. mi.texts.icaoLink .. ': ' .. vp.ParMap.icao
	end
	if t ~= '' then r = r .. ' (' .. t .. ')' end
	
	local leading = r
	r = ''

	-- additional part for vCard mode
	
	local period = ''

	-- adding address and direction
	if vp.ParMap.address ~= '' then
		r = r .. ', <bdi class="p-adr adr listing-address'
		if vc.wdContent.address then r = r .. ' wikidata-content' end
		r = r .. '"'
		if vp.ParMap.addressLang and vp.ParMap.addressLang ~= '' then
			r = r .. ' lang="' .. vp.ParMap.addressLang
				.. '" xml:lang="' .. vp.ParMap.addressLang .. '"'
				.. ' title="' .. mi.texts.hintAddress2 .. ' '
				.. lg.getProperty( vp.ParMap.addressLang, 'n' ) .. '"'
		end
		r = r .. '><span class="p-street-address street-address">'
			.. vp.ParMap.address .. '</span></bdi>'
	end
	if mi.options.showLocalData and ( vp.ParMap.addressLocal ~= '' ) then
		vp.ParMap.addressLocal =
			vc.languageSpan( vp.ParMap.addressLocal, mi.texts.hintAddress, wikiLang, country )
		r = r .. '<span class="listing-add-info">, <span class="listing-address-local'
		if vc.wdContent.addressLocal then r = r .. ' wikidata-content' end
		r = r .. '">' .. vp.ParMap.addressLocal .. '</span></span>'
	end
	
	t = ''
	if vp.ParMap.directions ~= '' then
		t = '<span class="listing-directions listing-emphasized'
		if vc.wdContent.directions then t = t .. ' wikidata-content' end
		t = t .. '">' .. vp.ParMap.directions .. "</span>"
	end
	s = ''
	if mi.options.showLocalData and ( vp.ParMap.directionsLocal ~= '' ) then
		s = '<span class="listing-add-info">, <span class="listing-directions-local'
		if vc.wdContent.directionsLocal then s = s .. ' wikidata-content' end
		s = s .. '">' .. vc.languageSpan( vp.ParMap.directionsLocal, mi.texts.hintDirections, wikiLang, country )
			.. '</span></span>'
	end
	if t ~='' then r = r .. ' (' .. t .. s .. ')'
		else r = r .. s end
	if r ~= '' then r = r .. '. '
		else period = '. ' end

	t = vc.formatPhone( 'phone', country, '' )
	t = vc.formatPhone( 'tollfree', country, t )
	t = vc.formatPhone( 'mobile', country, t )
	t = vc.formatPhone( 'fax', country, t )
	if vp.ParMap.email ~='' then
		if t ~= '' then t = t .. ', ' end
		t = t .. mi.texts.email .. ' <span class="u-email email listing-email'
		if vc.wdContent.email then t = t .. ' wikidata-content' end
		t = t .. '">' .. lm.linkMailSet( { email = vp.ParMap.email } ) .. '</span>'
	end
	if vp.ParMap.skype ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. mi.texts.skype .. ' <span class="listing-skype'
		if vc.wdContent.skype then t = t .. ' wikidata-content' end
		t = t .. '">' .. ls.linkSkypeSet( { skype = vp.ParMap.skype } ) .. '</span>'
	end
	if t ~= '' then
		r = r .. t .. '.'
	end
	
	t = ''
	if mi.options.showSisters == true then
		t, s = vc.addSisterIcons( sisters, vp.ParMap.wikidata, name.name, vp.ParMap.wikidata )
	end

	u = vc.formatSocial( 'facebook', 'facebook.com', 'https://www.facebook.com/', name.name )
		.. vc.formatSocial( 'flickr', 'flickr.com', 'https://www.flickr.com/photos/', name.name )
		.. vc.formatSocial( 'google', 'google.com', 'https://plus.google.com/', name.name )
		.. vc.formatSocial( 'instagram', 'instagram.com', 'https://www.instagram.com/', name.name )
		.. vc.formatSocial( 'twitter', 'twitter.com', 'https://twitter.com/', name.name )		
		.. vc.formatSocial( 'youtube', 'youtube.com', 'https://www.youtube.com/channel/', name.name )
	t = t .. u

	if t ~= '' then
		if t == s then
			-- only Wikidata icon. This is not visible for readers who are not logged in.
			r = r .. mw.ustring.gsub( t, '</span>', '.</span>' )
		else
			r = r .. t
			if u ~= '' then
				r = r .. '<span class="listing-social-media">.</span>'
			else
				r = r .. '<span class="listing-sister-icon">.</span>'
			end
		end
	end

	if vp.ParMap.description ~= '' and ( arrShow.inline or not descrDiv ) then
		r = r .. ' <span class="p-note note listing-content">' ..
			vp.ParMap.description .. '</span>'
	end

	r = r .. vc.formatText( 'hours', 'p-note note listing-hours' )
		.. vc.formatText( 'checkin', 'listing-checkin' )
		.. vc.formatText( 'checkout', 'listing-checkout' )
		.. vc.formatText( 'price', 'p-note note listing-price' )
	if vp.ParMap.payment ~= '' then
		u = 'p-note note listing-payment'
		if vc.wdContent.payment then -- vp.ParMap.payment is an array
			if #vp.ParMap.payment > 0 then
				u = u .. ' wikidata-content'
				for s = #vp.ParMap.payment, 1, -1 do
					t = vp.ParMap.payment[ s ]
					if vr[ t ] then
						vp.ParMap.payment[ s ] = vr[ t ]
					else
						table.remove( vp.ParMap.payment, s )
					end
				end
			end
			vp.ParMap.payment = table.concat( vp.ParMap.payment, ', ' )
		else
			errorMsgs = errorMsgs .. mi.errorMsg.paymentUsed
		end			
		r = r .. vc.formatText( 'payment', u )
	end

	if arrShow.subtype then
		-- merging subtypeAdd to arrSubtype
		value2 = type( vp.ParMap.subtypeAdd ) == 'table' and #vp.ParMap.subtypeAdd > 0
		if value2 then
			for s = 1, #vp.ParMap.subtypeAdd, 1 do
				t = vp.ParMap.subtypeAdd[ s ] -- Wikidata id
				if vs.t[ t ] then arrSubtype[ vs.t[ t ] ] = '' end
			end
		end
		
		t = ''
		if next( arrSubtype ) then
			for u = 2, vs.n, 1 do -- number of subtype groups
				for key, value in pairs( arrSubtype ) do
					s = vs.f[ key ]
					if s and s.g == u then
						if s.f ~= '' then
							t = t .. ' ' .. s.f
						else
							t = t .. ' [' .. key .. ']'
						end
					end
				end
			end
		end
		if t ~= '' then
			r = r .. ' <span class="listing-subtype'
			if value2 then
				r = r .. ' wikidata-content'
			end
			r = r .. '">' .. mi.texts.subtype .. ' ' .. t .. '.</span>'
		end
	end

	if vp.ParMap.unesco ~= '' then
		r = r .. ' <span class="listing-unesco">' .. mi.icons.unesco .. un.getArticleFromWD()
			.. '|' .. mi.texts.unesco .. ']]</span>'
	end

	-- adding DMS coordinates
	if arrShow.all or arrShow.coord then
		r = r .. ' ' .. mb.dmsCoordinates( vp.ParMap.lat, vp.ParMap.long, name.name, vc.wdContent.lat, extra, true )
	end

	if mi.options.showSisters == 'atEnd' then
		r,_ = r .. vc.addSisterIcons( sisters, vp.ParMap.wikidata, name.name, vp.ParMap.wikidata )
	end

	if vp.ParMap.description ~= '' and descrDiv then
		r = r .. '<div class="p-note note listing-content">\n' .. vp.ParMap.description
		-- last edit will be inserted at the end of the div tag
	end

	if vp.ParMap.lastedit ~='' then
		local success;
		success, t = pcall( vc.formatDate, vp.ParMap.lastedit, 'M Y' )
		if not success then
        	t = mi.errorMsg.wrongDate
        end
		r = r .. '<span class="listing-metadata"> (<span class="listing-metadata-items"><span class="listing-metadata-item listing-lastedit">'
			.. mi.texts.lastedit .. ' ' .. t
			.. '</span></span>)</span>'
	else
		r = r .. '<span class="listing-metadata"><span class="listing-metadata-items">&nbsp;</span></span>'
	end

	if vp.ParMap.description ~= '' and descrDiv then
		r = r .. '</div>'
	end

	r = mw.ustring.gsub( r, '(%.%.)', '.' )
	r = mw.ustring.gsub( r, '(%.</span>%.)', '</span>.' )
	r = mw.ustring.gsub( r, '(%.</span></span>%.)', '</span></span>.' )
	r = mw.ustring.gsub( r, '(%.</span></bdi>%.)', '</span></bdi>.' )
	
	if r == '' then r = leading else r = leading .. period .. r end

	-- wrapping tag

	if arrShow.inline then
		r = r .. '</span>'
	else
		r = r .. '</div>'
	end

	if vp.ParMap.wikidata ~= '' then errorMsgs = errorMsgs .. mi.errorMsg.wikidata end
	if wrongQualifier then errorMsgs = errorMsgs .. '<span class="error">'
		.. mi.errorMsg.wrongQualifier .. '</span>' end
	if cntrl then errorMsgs = errorMsgs .. '<span class="listing-error">'
		.. mi.errorMsg.illegalCtrls .. '</span>' end

	local ns = mw.title.getCurrentTitle().namespace
	if ns == 0 then return r .. errorMsgs
	else return r end
end

return vc