Logo Voyage

Module:Listing Voyage Tips and guide

You can check the original Wikivoyage article Here

--[[
	Source script:	https://it.wikivoyage.org/wiki/Modulo:Listing
	Maintainer:		Andyrom75

	Lazy loads:
	require('Module:IsLatin').IsLatinValue
	require('Module:EmailTracking').EmailTrackingValue
]]
local Marker = require('Module:Marker').MarkerModule
local LinkModule = require('Module:LinkPhone')
local MapLink = require('Module:MapLink').MapLinkModule
local i18n = require( 'Module:Listing/i18n' )
local par = i18n.parameters
local marPar = i18n.markerParameters

local function _templateStyle( frame, src )
   return frame:extensionTag( 'templatestyles', '', { src = src } )
end

local function _isDefined(s)
	return s ~= '' and s
end

local function _hiddenUnicode( value )
    -- Note the quote ("") below is not empty and actually contains a hidden unicode character.
    return mw.ustring.match(value or '',"‎") and '[[Category:' .. i18n.categories.hiddenChar .. ']]<span class="unicodeinfo debuginfo">' .. i18n.errorMsg.unicode .. '</span>' or ''
end

local function _email( mail )
    return '<span class="email listing-email">' .. LinkModule.LinkEmail{ args={mail} } .. '</span>' .. require('Module:EmailTracking').EmailTrackingValue(mail)
end

local function _concatIndexed( tab )
    local tt = {}
    for _, v in pairs( tab ) do
        tt[#tt+1] = v
    end
    return table.concat( tt )
end

local function _validateParams( params )
    -- costruisco l'elenco delle chiavi valide nella lingua configurata
    local validParams = {}
    for _, translatedKey in pairs(par) do
        validParams[translatedKey] = true
    end
	-- verifico se tra i parametri ricevuti ci sono solo e soltanto i parametri ammessi
	local invalidParams = ''
	for key, _ in pairs( params ) do
		if not validParams[key] then
			invalidParams = invalidParams .. '<b>' .. key ..'</b>; '
		end
	end
	return _isDefined(invalidParams) and (((mw.title.getCurrentTitle().namespace == 0) and ('[[Category:' .. i18n.categories.invalidPar .. ']]') or '') ..'<span class="debuginfo">' .. i18n.errorMsg.wrongPar .. invalidParams .. '</span>') or ''
end


local function _sanitizeCaption(s)
	s = s or ''
	s = s:gsub('[\r\n]+', ' ')						-- niente newline
	s = s:gsub('|', '&#124;')						-- pipe letterale
	s = s:gsub('%[', '&#91;'):gsub('%]', '&#93;')	-- quadre letterali
	return s
end

local function _renderAdjustment( content )
	if not _isDefined(content) then return '' end
	
	--Sostituisco temporaneamente gli stili dei template utilizzati all'interno delle descrizioni per il loro contenuto può compromettere la succeessiva elaborazione
	local styles = {}
	local style = ''
	local patterns = {'(style=".-")', "(style='.-')"}
	for i=1, #patterns do
		local pos = mw.ustring.find(content, patterns[i])
		while pos do
			style = mw.ustring.gsub(content, '.-'..patterns[i]..'.*', '%1')
			styles[#styles+1] = style
			content = mw.ustring.sub( content, 1, pos-1 ) .. "<<§@§>>" .. mw.ustring.sub( content, pos+#style)
			pos = mw.ustring.find(content, patterns[i])
		end
	end

	local level1 = not mw.ustring.find(content, '\n[*#][*#]') and not mw.ustring.find(content, '\n:+[*#:][*#]')
	if mw.ustring.find(mw.ustring.sub(content,1,1), '[:;*#]') then
		-- se la descrizione inizia con un carattere speciale, lo mando a capo affiché venga correttamente gestito dal wiki-interprete
		content = '\n' .. content
	end
	
	-- limito le dispendiose gsub ai casi di descrizioni con righe-multiple
	-- inoltre, per le attuali limitazioni, evito di elaborare le descrizioni contenenti liste HTML a più livelli
	if mw.ustring.find(content, '\n') and level1 then
		-- gestisco i casi più comuni di ";" sebbene ricreare l'esatto rendering del wiki-testo è praticamente impossibile
		if mw.ustring.find(content, ';') then
			content = mw.ustring.gsub(content, "(\n:*);(:*[*#])", "%1:%2")
			content = mw.ustring.gsub(content, "(\n):*;", "%1<<§>>")
			content = mw.ustring.gsub(content, "(\n:*([*#][:;]*));", "%1<<§>>")
			content = mw.ustring.gsub(content, "<<§>>(.-)\n", "<dl><dt>%1</dt></dl>\n")
			content = mw.ustring.gsub(content, "<<§>>(.-)$", "<dl><dt>%1</dt></dl>")
		end
		local isUnorderedList = mw.ustring.find(content, '\n:* *%*') or mw.ustring.find(content, '^:* *%*')
		local isOrderedList = mw.ustring.find(content, '\n:* *%#') or mw.ustring.find(content, '^:* *%#')
		-- per attuali limitazioni elaboro solo descrizioni contenenti un unico tipo di liste
		if (isUnorderedList and not isOrderedList) or (isOrderedList and not isUnorderedList) then
			--contrassegno l'inizio di ogni item con un simbolo potenzialmente univoco
			content = mw.ustring.gsub(content, "\n:? *[*#]", "\n<<§>>")
			content = mw.ustring.gsub(content, "<<§>>(.-)\n", "<li>%1</li>\n")
			content = mw.ustring.gsub(content, "<<§>>(.-)$", "<li>%1</li>")
			content = mw.ustring.gsub(content, "</li>\n*:*<li>", "</li><li>")
			if isUnorderedList then
				content = mw.ustring.gsub(content, "(<li>.-</li>\n)", "<ul>%1</ul>\n")
				content = mw.ustring.gsub(content, "(<li>.*</li>)$", "<ul>%1</ul>")
				content = mw.ustring.gsub(content, "</ul>\n:", "</ul>")
			elseif isOrderedList then
				content = mw.ustring.gsub(content, "(<li>.-</li>\n)", "<ol>%1</ol>\n")
				content = mw.ustring.gsub(content, "(<li>.*</li>)$", "<ol>%1</ol>")
				content = mw.ustring.gsub(content, "</ol>\n:", "</ol>")
			end
		end
		-- per attuali limitazioni evito di elaborare descrizioni contenenti sia liste ordinate che non ordinate
		if not (isUnorderedList and isOrderedList) then
			content = mw.ustring.gsub(content, "\n:+", "<br />")
			content = mw.ustring.gsub(content, "\n\n", "<br />")
			content = mw.ustring.gsub(content, "\n([^\n]+)", "%1")
		end
	end
	--ripristino gli stili rimossi
	for i=1, #styles do
		content = mw.ustring.gsub(content , '<<§@§>>', styles[i], 1)
	end
	return content
end

local function _Listing(frame)
	local args = frame.args
	local output = '<bdi class="vcard">'
	local outputPriceForEnVoy = ''
	--Marker creation
	local MarkerArgs = {
		[marPar.counter] = args[par.counter] or args[par.mtype] or 'listing',
		[marPar.mtype] = args[par.mtype] or 'listing',
		[marPar.name] = args[par.name],
		[marPar.lat] = args[par.lat],
		[marPar.long] = args[par.long],
		[marPar.image] = args[par.image],
		[marPar.url] = args[par.url],
		[marPar.islisting] = i18n.msg.yes,
		[marPar.wikidata] = args[par.wikidata]
	}
	output = output .. Marker{ args = MarkerArgs }

	--Alt
	if _isDefined( args[par.alt] ) then
		output = output .. '&#32;(<span class="nickname listing-alt ' .. (require('Module:IsLatin').IsLatinValue(args[par.alt]) == 1 and 'IsLatin' or '') .. '">' .. args[par.alt] .. '</span>)'
	end

	--Indirizzo
	local anyPrevData = args[par.name] or args[par.url]
	if _isDefined( args[par.address] ) then
		output = output .. (anyPrevData and ',' or '') .. '&#32;<span class="adr listing-address street-address">' .. args[par.address] .. '</span>'
		anyPrevData = true
	end

	--indicazioni
	if _isDefined( args[par.directions] ) then
		output = output .. '&#32;(<span class="adr listing-directions">' .. args[par.directions] .. '</span>)'
		anyPrevData = true
	end

	--Telefono
	if _isDefined( args[par.tel] ) then
		output = output .. (anyPrevData and ',' or '')
			.. '&#32;<abbr title="' .. i18n.msg.phone .. '" class="listing-phone-symbol">' .. i18n.symbols.phone .. '</abbr> <span class="tel listing-phone">'
			.. LinkModule.LinkPhone{ args={args[par.tel]} }
			.. '</span>'
		anyPrevData = true
	end

	--Numero Verde
	if _isDefined( args[par.tollfree] ) then
		output = output .. (anyPrevData and ',' or '')
			.. '&#32;<abbr title="' .. i18n.msg.tollfree .. '" class="listing-tollfree-symbol">' .. i18n.symbols.tollfree .. '</abbr> <span class="tel listing-tollfree">'
			.. LinkModule.LinkTollfree{ args={args[par.tollfree]} }
			.. '</span>'
		anyPrevData = true
	end

	--Fax
	if _isDefined( args[par.fax] ) then
		output = output .. (anyPrevData and ',' or '')
			.. '&#32;<span class="tel"><span class="type">fax</span>: <span class="value listing-fax">'
			.. LinkModule.LinkFax{ args={args[par.fax]} }
			.. '</span></span>'
		anyPrevData = true
	end

	--E-mail
	if _isDefined( args[par.email] ) then
		output = output .. (anyPrevData and ',&#32;' or '&#32;') .. _email(args[par.email])
	end

	--Se sono state inserite informazioni nei campi precedenti, forzo un punto di fine periodo
	output = output .. (anyPrevData and '.' or '')

	--Prezzo
	if _isDefined( args[par.price] ) then
		local outputPrice = '&#32;'
			.. (_isDefined(i18n.msg.price) and _isDefined(i18n.icons.price) and ('<abbr title="' .. i18n.msg.price .. '">[[File:' .. i18n.icons.price .. '|13px|class=listing-price-icon|link=]]</abbr> ') or '')
			.. '<span class="note listing-price">' .. args[par.price] .. '</span>.'
		if i18n.wiki.home == 'enwikivoyage' then
			outputPriceForEnVoy = outputPrice
		else
			output = output .. outputPrice
		end
	end

	--Orari
	if _isDefined( args[par.hours] ) then
		output = output .. '&#32;'
			.. (_isDefined(i18n.msg.hours) and _isDefined(i18n.icons.hours) and ('<abbr title="' .. i18n.msg.hours .. '">[[File:' .. i18n.icons.hours .. '|15px|class=listing-hours-icon|link=]]</abbr> ') or '')
			.. '<span class="note listing-hours">' .. args[par.hours] .. '</span>.'
	end

	--Check-in e checkout
	if _isDefined( args[par.checkin] ) then
		output = output .. '&#32;<span class="note">Check-in: <span class="listing-checkin">' .. args[par.checkin] .. '</span>'
		if _isDefined( args[par.checkout] ) then
			output = output .. ', check-out: <span class="listing-checkout">' .. args[par.checkout] .. '</span>'
		end
		output = output .. '</span>.'
	else
		if _isDefined( args[par.checkout] ) then
			output = output .. '&#32;<span class="note">Check-out: <span class="listing-checkout">' .. args[par.checkout] .. '</span></span>.'
		end
	end

	--Descrizione generale del listing in oggetto
	args[par.description] = _isDefined( args[par.description] ) or _isDefined( args[1] )
	if args[par.description] then
		args[par.description] = _renderAdjustment( args[par.description] )
		output = output .. '&#32;<bdi class="note listing-content">' .. args[par.description] .. '</bdi>'
	end
	-- eccezione per en:voy
	output = output .. outputPriceForEnVoy

	--Sister project icons
	local metadata = ''
	local wpLink = _isDefined( args[par.wikipedia] )
	if _isDefined( args[par.wikidata] ) then
		--in presenza dell'istanza wikidata, recupero i dati relativi a Wikivoyage e Wikipedia
		local WIB_wikivoyage = _isDefined( mw.wikibase.getSitelink(args[par.wikidata], i18n.wiki.home) )
		if WIB_wikivoyage then
			metadata = metadata .. '&#32;[[File:' .. i18n.icons.wikivoyage .. '|15px|class=listing-sister-wikivoyage|link=' .. WIB_wikivoyage .. '|' .. WIB_wikivoyage .. i18n.msg.wikivoyage .. ']]'
		end
		wpLink = wpLink or _isDefined( mw.wikibase.getSitelink(args[par.wikidata], i18n.wiki.wikipedia) )
	end
	if _isDefined( args[par.wikipedia] ) ~= 'NA' and wpLink then
		metadata = metadata .. '&#32;[[File:' .. i18n.icons.wikipedia .. '|15px|class=listing-sister-wikipedia|link=w:' .. wpLink .. '|' .. wpLink .. i18n.msg.wikipedia .. ']]'
	end
	if _isDefined( args[par.wikidata] ) then
		metadata = metadata .. '&#32;[[File:' .. i18n.icons.wikidata .. '|16px|class=listing-sister-wikidata|link=d:' .. args[par.wikidata]
			..'|' .. (_sanitizeCaption(mw.wikibase.label(args[par.wikidata])) or '') .. ' ('.. args[par.wikidata] .. ')' .. i18n.msg.wikidata .. ']]'
	end
	if _isDefined( args[par.facebook] ) then
		metadata = metadata .. '&#32;[[File:' .. i18n.icons.facebook .. '|16px|class=listing-sister-facebook|link=' .. args[par.facebook] ..'|' .. i18n.msg.facebook .. ']]'
	end
	if _isDefined( args[par.twitter] ) then
		metadata = metadata .. '&#32;[[File:' .. i18n.icons.twitter .. '|16px|class=listing-sister-twitter|link=' .. args[par.twitter] ..'|' .. i18n.msg.twitter .. ']]'
	end
	if args[par.osm] ~= 'no' then
		metadata = metadata .. MapLink{ args = {lat=args[par.lat], long=args[par.long], wikidata=args[par.wikidata], map='osm'} }
	end
	metadata = metadata .. MapLink{ args = {lat=args[par.lat], long=args[par.long], wikidata=args[par.wikidata], map='apple'} }
	metadata = metadata .. MapLink{ args = {lat=args[par.lat], long=args[par.long], wikidata=args[par.wikidata], map='google'} }
	if _isDefined( metadata ) then
		metadata = '<span class="noprint listing-sister-icons">' .. metadata .. '</span>'
	end

	--Metadata - last edit date, "edit" link, etc
	local metadata2B, metadata2, metadata2E = '', '', ''
	if _isDefined( args[par.lastedit] ) then
		metadata2B = '('
		metadata2 = '<span class="listing-lastedit">'  .. i18n.msg.lastedit .. mw.getContentLanguage():formatDate( 'M Y', args[par.lastedit] ) .. '</span>'
		metadata2E = ')'
	end
	metadata = metadata .. '<span class="listing-metadata">&nbsp;' .. metadata2B .. '<span class="listing-metadata-items">' .. metadata2 .. '</span>' .. metadata2E .. '</span>'
	local match = 0
	output, match = mw.ustring.gsub( output, "(</dt></dl></li></[uo]l></bdi>)$", metadata .. "%1")
	if match == 0 then
		output, match = mw.ustring.gsub( output, "(</..></[uod]l></bdi>)$", metadata .. "%1")
		if match == 0 then
			output = output .. metadata
		end
	end


	output = output .. '</bdi>'

	--Controllo la presenza di caratteri Unicode all'interno dei parametri forniti in input
	--A seguire controllo anche la presenza di parametri non gestiti da questo template
	output = output .. _hiddenUnicode( _concatIndexed( args ) ) .. _validateParams( args )
	if args[par.wikipedia] and not args[par.wikidata] then
			--Non è considerato un errore se il parametro Wikipedia è usato per puntare a una specifica sezione
			output = output .. (mw.ustring.find(args[par.wikipedia], '#') == 0 and '[[Category:' .. i18n.categories.noWikidata .. ']]' or '')
	end

    return _templateStyle( frame, 'Listing/styles.css' ) .. output
end

local p = {}

function p.ListingTemplate(frame)
	return _Listing(frame:getParent())
end

function p.ListingInvoke(frame)
	return _Listing(frame)
end

function p.ListingTemplateAndInvoke(frame)
    -- faccio una copia di args del template genitore
    local mergedArgs = {}
    local parentFrame = frame and frame:getParent()
    if parentFrame and parentFrame.args then
        for k, v in pairs(parentFrame.args) do
            mergedArgs[k] = v
        end
    end

    -- sovrascrivo/aggiungo args passati direttamente all'#invoke
    if frame and frame.args then
	    for k, v in pairs(frame.args) do
	        mergedArgs[k] = v
	    end
    end

	-- creo un nuovo frame con la fusione dei due args
    local title = frame:getTitle()
    local mergedFrame = frame:newChild{ title = title, args = mergedArgs }
	return _Listing(mergedFrame)
end

function p.ListingModule(frame)
	local Cframe = mw.getCurrentFrame()
	Cframe.args = frame.args
	return _Listing(Cframe)
end

return p


Discover



Powered by GetYourGuide