Módulo:Software

Īhuīcpa Huiquipedia, in yōllōxoxouhqui cēntlamatilizāmoxtli

La documentación para este módulo puede ser creada en Módulo:Software/doc

local p = {}
local ModuloArgumentos	= require('Módulo:Argumentos')
local ModuloFicha		= require('Módulo:Amatl')
local ModuloWikidata	= require('Módulo:Wikidata')
local ModuloPaginas		= require('Módulo:Centlaixtli')
local elementoTabla		= require('Módulo:Tablas').elemento
local getUnit			= require('Módulo:Wikidata/cemaxcayotl').main
local esUnValor			= ModuloWikidata.esUnValor
local argumentos		= ModuloArgumentos.obtenerValorDeArgumentos
local Entidad, InstanciaDe

-- :: Estilos
local ColorTitulo		= '#DCEAEC'
local ColorTituloTexto	= '#000'
local ColorEtiqueta		= '#eef5f6'
local EstiloTitulo
local EstiloSeccion		
local EstiloEtiqueta	= 'width:35%'
local EstiloDatos		= 'width:65%'

local Clasificacion		= mw.loadData('Módulo:Software/xelihuiliztli')

function p.Ficha(frame)
	-- :: Inicializador
	ModuloWikidata:setFrame(frame)
	ModuloArgumentos.obtenerTablaDeArgumentos(frame)
	Entidad			= mw.wikibase.getEntity(argumentos{'id'}) or mw.wikibase.getEntity(argumentos{'entidad'}) or {}
	InstanciaDe		= propiedad('P31', {['formato'] = 'entidadID'})

	-- :: Datos básicos
	Titulo			= argumentos{'name', 'nombre', {ModuloWikidata.obtenerEtiquetaWikidata, Entidad}, {ModuloPaginas.nombrePagina, {desambiguar='sí'}}}
	local ParteDe	= argumentos{'familia', 'family', {propiedad, 'P279', {['linkback'] = 'no'}}, {propiedad, 'P179', {['linkback'] = 'no'}}, {propiedad, 'P361', {['linkback'] = 'no'}}}
	local Familia
	if ParteDe then
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'componenteOS' then
			Familia = "''Componente de " .. ParteDe .. "''"
		elseif Clasificacion['TipoSoftware'][InstanciaDe] == 'OS' then
			Familia = "''Parte de la familia " .. ParteDe .. "''"
		else
			Familia = "''Parte de " .. ParteDe .. "''"
		end
	end

	-- :: Propiedades
	local Captura		= argumentos{'captura'}
	local Pie
	if Captura then
		Pie				= argumentos{'pie'}
	else
		Captura, Pie	= ModuloWikidata.obtenerImagenWikidata(Entidad, 'P18')
	end
	local Tamano		= argumentos{'tamaño'}-- or '250px'

	local Logo			= argumentos{'logo'} or ModuloWikidata.obtenerImagenWikidata(Entidad, 'P154') or ''
	local TamanoLogo	= argumentos{'tamaño_logo'} or '100px'

	-- :: Datos generales
	local Alias				= argumentos{'alias', {propiedad, 'P2561',{['lista'] = 'nobullet'}}}
	local NombreTecnico		= argumentos{'nombre_técnico', {propiedad, 'P1845', {['lista'] = 'nobullet', ['calificativo'] = 'P50'}}} or ''
	if string.len(NombreTecnico) > 200 then
		NombreTecnico	= seccionDesplegable(frame, 'varios', NombreTecnico)
	end
	local NombreCodigo		= argumentos{'nombre_código', {propiedad, 'P1638', {['lista'] = 'nobullet'}}}
	
	local Genero
	if Clasificacion['TipoSoftware'][InstanciaDe] == 'OS' or Clasificacion['TipoSoftware'][InstanciaDe] == 'componenteOS' then
		Genero				= argumentos{'género', {propiedad, 'P366', {['uno'] = 'sí'}}}
	else
		Genero				= argumentos{'género', {propiedad, 'P31', {['uno'] = 'sí'}}}
	end

	local Licencia	= argumentos{'licencia', {propiedad, 'P275', {['lista'] = 'nobullet'}}} or ''
	if string.len(Licencia) > 200 then
		Licencia	= seccionDesplegable(frame, '[[Licencia dual|varias]]', Licencia)
	end

	local ModeloDesarrollo	= argumentos{'modelo_desarrollo', {obtenerModeloDesarrollo}}

	local Desarrollador		= argumentos{'desarrollador', {propiedad, 'P178', {['lista'] = 'nobullet'}}}
	local Autor				= argumentos{'autor', {propiedad, 'P170', {['lista'] = 'nobullet'}}}
	
	local EstadoActual		= argumentos{'estado_actual', 'estado', 'working_state'}
	
	local Discontinuacion	= argumentos{'discontinuación', 'descontinuación', {propiedad, 'P2669', {['linkback'] = 'no'}}}

	-- :: Malware y vulnerabilidades
	local CVE	   			= argumentos{'identificador_cve', 'cve', 'vulnerabilidades', {propiedad, 'P3587', {['lista'] = 'nobullet'}}} or ''
	if string.len(CVE) > 200 then
		CVE					= seccionDesplegable(frame, 'varias', CVE)
	end
	
	local CVETitulo			= '[[Inseguridad informática|Vulnerabilidades]]'
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then CVETitulo = '[[CVE|Identificador CVE]]' end

	local Descubrimiento	= argumentos{'descubrimiento', {propiedad, 'P575', {['uno'] = 'sí'}}}
	local Parchado			= argumentos{'parchado', {propiedad, 'P582', {['uno'] = 'sí'}}}
	local Descubridor		= argumentos{'descubridor', {propiedad, 'P61', {['lista'] = 'nobullet'}}}
	local SoftwareAfectado	= argumentos{'software_afectado', {propiedad, 'P1547',{['calificador']='P348', ['lista'] = 'nobullet'}}}
	local Precio			= argumentos{'precio'}
	if not Precio then
		local PR = elementoTabla(Entidad, 'claims', 'P2284', 1)
		if PR then
			Precio = getUnit(elementoTabla(PR, 'mainsnak', 'datavalue', 'value', 'unit')) .. string.sub(elementoTabla(PR, 'mainsnak', 'datavalue', 'value', 'amount'), 2)
		else
			Precio = ''
		end
	end
	
	local PrecioTitulo		= 'Precio de venta'
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then PrecioTitulo = 'Precio de rescate' end

	-- :: Datos técnicos
	local LenguajeProgramacion	= argumentos{'lenguaje_programación', {propiedad, 'P277', {['lista'] = 'nobullet'}}}

	local SistemaOperativo
	if not Clasificacion['TipoSoftware'][InstanciaDe] == 'OS' then
		SistemaOperativo		= argumentos{'sistema_operativo', 'sistemas_operativos', {propiedad, 'P306', {['lista'] = 'nobullet'}}} or ''
		if string.len(SistemaOperativo) > 200 then
			SistemaOperativo		= seccionDesplegable(frame, '[[multiplataforma]]', SistemaOperativo)
		end
	end
	
	local Plataforma			= argumentos{'plataforma', {propiedad, 'P400', {['lista'] = 'nobullet'}}}
	local TamanoArchivo			= argumentos{'tamaño de archivo', {propiedad, 'P3575', {['uno'] = 'sí'}}}
	local Nucleo				= argumentos{'núcleo', 'kernel'} or Clasificacion['Nucleos'][ParteDe] or Clasificacion['Nucleos'][InstanciaDe]
	local TipoNucleo			= argumentos{'núcleo_tipo', 'kernel_tipo'}
	local GUI					= argumentos{'ui', {propiedad, 'P1414', {['lista'] = 'nobullet'}}}

	-- :: Datos de actualización
	local AdminPaquetes			= argumentos{'administrador_paquetes', {propiedad, 'P3033', {['lista'] = 'nobullet'}}}
	local MetodoActualizacion	= argumentos{'método_actualización', 'modelo_actualización', {propiedad, 'P4387', {['lista'] = 'nobullet'}}}

	-- :: Idiomas
	local Idiomas				= argumentos{'idiomas', {propiedad, 'P407', {['lista'] = 'nobullet'}}} or ''
	if string.len(Idiomas) > 200 then
		Idiomas		= seccionDesplegable(frame,'[[multilingüe]]', Idiomas)
	end

	local Espanol
	if not Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then
		Espanol			= argumentos{'español', 'castellano', {esUnValor, Entidad, 'P407', 'Q1321'}}
		if Espanol then
			if Espanol == 'No' or Espanol == 'no' then
				Espanol		= 'No'
			else
				Espanol		= 'Sí'
			end
		end
	end
	
	-- :: Otros datos
	local Estandares			= argumentos{'estándares'}
	local Motores				= argumentos{'motores', {propiedad, 'P408', {['lista'] = 'nobullet'}}}
	local Dependencias
	if not Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then
		Dependencias			= argumentos{'dependencias', {propiedad, 'P1547',{['calificador']='P348'}}}
		if Dependencias then
			Dependencias		= seccionDesplegable(frame, 'dependencias', Dependencias)
		end
	end

	local ArchivosLegibles		= argumentos{'formatos_legibles', {propiedad, 'P1072', {['lista'] = 'nobullet', ['linkback'] = 'no'}}} or ''
	if string.len(ArchivosLegibles) > 300 then
		ArchivosLegibles	= seccionDesplegable(frame, 'varios', ArchivosLegibles)
	end
	local ArchivosEditables	= argumentos{'formatos_editables', {propiedad, 'P1073', {['lista'] = 'nobullet', ['linkback'] = 'no'}}} or ''
	if string.len(ArchivosEditables) > 300 then
		ArchivosEditables	= seccionDesplegable(frame, 'varios', ArchivosEditables)
	end

	-- :: Asistencia técnica
	local AsistenciaTecnica
	local Soporte			= argumentos{'soporte'}
	local InicioSoporte		= argumentos{'inicio_soporte'}
	local FinSoporte		= argumentos{'fin_soporte'}
	local InicioSoporteExt	= argumentos{'inicio_soporte_extendido'}
	local FinSoporteExt		= argumentos{'fin_soporte_extendido'}
	if (not InicioSoporte and not FinSoporte and not InicioSoporteExt and not FinSoporteExt) and Soporte then
		if Soporte then
			AsistenciaTecnica	= '<span style="font-size:smaller">' .. Soporte .. '</span>' or ''
		end
	end

	-- :: Cronología y versiones
	-- Lanzamiento inicial
	local LanzamientoInicial	= argumentos{'lanzamiento'}
	local LanzamientoInicialRef
	local LanzamientoInicialFecha
	local LanzamientoInicialWeb
	local LanzamientoInicialDominio
	local LanzamientoInicialAcceso
	if not LanzamientoInicial then
		LanzamientoInicialRef		= {}
		LanzamientoInicial		= propiedad('P571', {['linkback'] = 'no', ['uno'] = 'sí'})
		LanzamientoInicialWeb		= argumentos{'web lanzamiento', 'web_lanzamiento'}
		if LanzamientoInicialWeb then LanzamientoInicialDominio	= LanzamientoInicialWeb:match('^%w+://([^/]+)') end
		LanzamientoInicialAcceso	= argumentos{'fecha acceso web lanzamiento', 'fecha_acceso_web_lanzamiento'}

		if LanzamientoInicialFecha	then
			LanzamientoInicial = LanzamientoInicial .. '<small>(' .. LanzamientoInicialFecha .. ')</small>'
			LanzamientoInicialRef['fecha'] = LanzamientoInicial
			if LanzamientoInicialWeb		then LanzamientoInicialRef['url']		= LanzamientoInicialWeb end
			if LanzamientoInicialDominio	then LanzamientoInicialRef['sitioweb']	= LanzamientoInicialDominio end
			if LanzamientoInicialAcceso		then LanzamientoInicialRef['fechaacceso'] = LanzamientoInicialAcceso end
			if next(LanzamientoInicialRef)	then 
				LanzamientoInicialRef['título'] = 'Web lanzamiento inicial'
				LanzamientoInicial = LanzamientoInicial .. citar(frame, LanzamientoInicialRef)
			end
		end
	end
	
	local Versiones					= obtenerVersiones(frame) or {}
	local VersionesHistorial		= argumentos{'versiones'} or Versiones['lista']
	local UltimaVersionEstable		= argumentos{'última_versión'} or Versiones['estable']
	local UltimaVersionBeta			= argumentos{'última_versión_prueba'} or Versiones['beta']

	-- Cronología
	local PrecedidoPor			= argumentos{'predecesor', {propiedad, 'P155', {['linkback'] = 'no'}}, {propiedad, 'P1365', {['linkback'] = 'no'}}}
	local SucedidoPor			= argumentos{'sucesor', {propiedad, 'P156', {['linkback'] = 'no'}}, {propiedad, 'P1366', {['linkback'] = 'no'}}}
	local CronologiaTitulo		= argumentos{'cronología'}
	--local CronologiaActual		= Titulo
	if PrecedidoPor or SucedidoPor then
		if not CronologiaTitulo then
			if ParteDe then
				CronologiaTitulo= 'Serie ' .. ParteDe
			else
				CronologiaTitulo=  'Lanzamientos'
			end
		end
	end

	-- :: Otras secciones
	local OtrosArticulos	= argumentos{'otros_artículos', {propiedad, 'P1659', {['lista'] = 'nobullet', ['linkback'] = 'no'}}}
	local SitiosWeb			= obtenerEnlaces()
	local ClaseTitulo		= 'software'
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then ClaseTitulo = 'virus' end
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'componenteOS' then ClaseTitulo = 'ingeniería' end
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'OS' then ClaseTitulo = 'pc' end
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'web' then ClaseTitulo = 'internet' end
	
	local GeneroTitulo		= 'Tipo de programa'
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then GeneroTitulo = 'Clasificación' end

	local PlataformaTitulo	= '[[Plataforma (informática)|Plataformas admitidas]]'
		if Clasificacion['TipoSoftware'][InstanciaDe] == 'malware' then PlataformaTitulo = 'Hardware afectado' end

	-- :: Estilos
	EstiloTitulo			= ';background-color:' .. ColorTitulo
	EstiloSeccion			= 'background-color:' .. ColorTitulo
	EstiloEtiqueta			= EstiloEtiqueta .. ';background-color:' .. ColorEtiqueta
	--EstiloDatos				= EstiloEtiqueta--

	-- :: La ficha
	local TablaFicha = {
		titulo  			= Titulo,
		subtitulo			= Familia,
		clasetitulo			= ClaseTitulo,
		estilotitulo		= EstiloTitulo,
		estiloseccion		= EstiloSeccion,
		estiloetiqueta		= EstiloEtiqueta,
		estilodatos			= EstiloDatos,
		imagen				= Logo,
		['tamañoimagen']	= TamanoLogo,
		--estiloimagen		= 'max-height:150px',
		imagen2				= Captura,
		['tamañoimagen2']	= Tamano,
		pie2				= Pie,
		estilopie2			= 'font-size:88%',
		{tipo='sección',
			titulo = 'Información general',
			{'[[Anexo:Géneros de software|'.. GeneroTitulo .. ']]', Genero},
			{'Alias', Alias},
			{'Nombre técnico', NombreTecnico},
			{'Nombre código', NombreCodigo},
			{'Autor', Autor},
			{'[[Desarrollador de software|Desarrollador]]', Desarrollador},
			{'[[Ingeniería de software|Modelo de desarrollo]]', ModeloDesarrollo},
			{'Lanzamiento inicial', LanzamientoInicial},
			{'Discontinuación', Discontinuacion},
			{CVETitulo, CVE},
			{'Fecha de descubrimiento', Descubrimiento},
			{'Fecha de parchado', Parchado},
			{'Descubridor', Descubridor},
			{'Software afectado', SoftwareAfectado},
			{PrecioTitulo, Precio},
			{'[[Licencia de software|Licencia]]', Licencia},
			{'Estado actual', EstadoActual},
			{'[[Idioma]]s', Idiomas},
			{'[[Idioma español|En español]]', Espanol} -- Este parámetro no me gusta
		},
		{tipo='sección',
			titulo = 'Información técnica',
			{'[[Lenguaje de programación|Programado en]]', LenguajeProgramacion},
			{'[[Sistema operativo]]', SistemaOperativo},
			{'[[Núcleo (informática)|Núcleo]]', Nucleo},
			{'Tipo de núcleo', TipoNucleo},
			{'Tamaño', TamanoArchivo},
			{PlataformaTitulo, Plataforma},
			{'[[Interfaz gráfica de usuario|Interfaz gráfica]] predeterminada', GUI},
			{'[[Sistema de gestión de paquetes]]', AdminPaquetes},
			{'[[Parche (informática)|Método de actualización]]', MetodoActualizacion},
			{'[[Norma (tecnología)|Estándares]]', Estandares},
			--{'[[Motor de software|Motor]]', Motores},
			{'Motor', Motores},
		},
		{tipo='sección',
			estilodatos	= 'text-align:left',
			titulo		= 'Versiones',
			{'[[Ciclo de vida del lanzamiento de software|Última versión estable]]', UltimaVersionEstable},
			{'[[Ciclo de vida del lanzamiento de software|Última versión en pruebas]]', UltimaVersionBeta},
			{'Historial de versiones', VersionesHistorial},
		},
		{tipo = 'sección',
			titulo = CronologiaTitulo,
			{tipo='sucesión',
				anterior = PrecedidoPor or '',
				actual = CronologiaActual or '',
				siguiente = SucedidoPor or '',
			},
		},
		{tipo='sección',
			estilodatos	= 'text-align:left',
			titulo		= 'Dependencias',
			{'', Dependencias}
		},
		{tipo='sección',
			estilodatos	= 'text-align:left',
			titulo		= 'Archivos legibles',
			{'', ArchivosLegibles}
		},
		{tipo='sección',
			estilodatos	= 'text-align:left',
			titulo		= 'Archivos editables',
			{'', ArchivosEditables}
		},


		{tipo='sección',
			titulo = 'Asistencia técnica',
			{'', AsistenciaTecnica},
			{'Inicio soporte', InicioSoporte},
			{'Fin soporte', InicioSoporte},
			{'Inicio soporte extendido', InicioSoporteExt},
			{'Fin soporte extendido', InicioSoporteExt},
		},
		{tipo='sección',
			titulo = 'Artículos relacionados',
			estilodatos	= 'text-align:left',
			{'', OtrosArticulos}
		},
		{tipo='sección',
			titulo = 'Enlaces',
			--estilodatos	= 'text-align:left',
			{'', SitiosWeb}
		},
	}
	return ModuloFicha.infobox(TablaFicha)
end

function generarEnlace(enlace, texto)
	local enlazar = require('Módulo:URL').enlazar
	enlace = enlace:match('.+:?//(.+) .+$') or enlace
	enlace = enlazar(enlace, texto) or ''
	enlace = enlace and '<div>'..enlace..'</div>\n'
	return enlace
end

function obtenerEnlaces()
	str = ''
	local SitioWeb		= argumentos{'sitio_web', 'sitio web', 'web'}
	if not SitioWeb then
		-- WIP, se pretende buscar a través de los valores de P856, y encontrar el que está en español, junto con la versión archivada, de estarlo
		SitioWeb = elementoTabla(Entidad, 'claims', 'P856', 1)
		if SitioWeb then
			SitioWebVals	= elementoTabla(SitioWeb, 'mainsnak', 'datavalue' ,'value')
			--SitioWebArchivo = elementoTabla(SitioWeb, 'qualifiers', 'P1065', 'datavalue' ,'value')
			--if SitioWebArchivo then
			--	str = str..generarEnlace(SitioWebArchivo, 'Sitio web oficial (archivo)')
			--end
			str = str..generarEnlace(SitioWebVals, 'Sitio web oficial')
		end
	else
		str = str..generarEnlace(SitioWeb, 'Sitio web oficial')
	end

	local Blog = argumentos{'blog_oficial', {propiedad, 'P1581',{['enlace']='no', uno='sí'}}}
	if Blog then
		str = str..'<div>'..generarEnlace(Blog, 'Blog')
	end

	local Repo = argumentos{'repositorio', {propiedad, 'P1324',{['enlace']='no', uno='sí'}}}
	if Repo then
		str = str..'<div>'..generarEnlace(Repo, 'Repositorio de código')
	end

	local SegErrores = argumentos{'seguimiento_de_errores', {propiedad, 'P1401',{['enlace']='no', uno='sí'}}}
	if SegErrores then
		str = str..'<div>'..generarEnlace(SegErrores, 'Seguimiento de errores')
	end
	return str
end

function seccionDesplegable(frame, titulo, lista)
	if not lista then return end
	return frame:preprocess('{{Sección desplegable|align=left|título=' .. titulo .. '|datos='.. lista .. '|estilotitulo=background-color:' .. ColorEtiqueta .. ';}}')
end

function obtenerModeloDesarrollo()
	if Clasificacion['Nucleos'][ParteDe] == 'xnu' then
		return '[[código cerrado]] con componentes de [[código abierto]]'
	end

	if Clasificacion['Nucleos'][InstanciaDe] == 'linux' or Clasificacion['Nucleos'][ParteDe] == 'linux' or Clasificacion['Nucleos'][ParteDe] == 'bsd' or Clasificacion['TipoSoftware'][InstanciaDe] == 'códigoAbierto' then
		return '[[código abierto]]'
	end
end

function obtenerVersiones(frame)
	local Versiones			= elementoTabla(Entidad, 'claims', 'P348')
	local VersionesEstables	= {}
	local VersionesBeta		= {}
	
	local Autoref	= argumentos{'autoref'}
	Autoref			= 'sí' -- Solo para depuración

	if Versiones then
		for k,v in pairs(Versiones) do
			VersionValor		= elementoTabla(v, 'mainsnak', 'datavalue', 'value')
			VersionTitulo		= elementoTabla(v, 'qualifiers', 'P1476', 1, 'datavalue', 'value', 'text')
			VersionFecha		= elementoTabla(v, 'qualifiers', 'P577', 1, 'datavalue', 'value')
			VersionTipo			= elementoTabla(v, 'qualifiers', 'P548', 1, 'datavalue', 'value', 'id')

			if VersionTitulo then VersionValor = VersionTitulo end

			VersionRefURL		= elementoTabla(elementoTabla(v, 'references', 1), 'snaks', 'P854',  1, 'datavalue', 'value')
			
			if not VersionRefURL == nil then
				VersionValor = '<span class="plainlinks">[' .. VersionRefURL .. ' ' .. VersionValor .. ']</span>'
			end
			
			if VersionFecha then
				VersionValor = VersionValor .. '<br><small>' .. require('Módulo:Wikidata/Fecha').FormateaFechaHora(VersionFecha, {}) .. '</small>' end

			if VersionTipo == 'Q2804309' then
				table.insert(VersionesEstables, VersionValor)
			elseif VersionTipo == 'Q3295609' then
				table.insert(VersionesBeta, VersionValor)
			end
		end

		table.sort(VersionesEstables, function(a, b) return a > b end)
		table.sort(VersionesBeta, function(a, b) return a > b end)

		Versiones			= {}

		if VersionesEstables[2] then table.insert(Versiones, seccionDesplegable(frame, 'Estables', '* ' .. table.concat(VersionesEstables, '\n* '))) end
		if VersionesBeta[2] then table.insert(Versiones, seccionDesplegable(frame, 'Pruebas', '* ' .. table.concat(VersionesBeta, '\n* '))) end

		if Versiones[2] then return {['lista'] = table.concat(Versiones, '\n'), ['estable'] = VersionesEstables[1], ['beta'] = VersionesBeta[1]} end
		return {['estable'] = VersionesEstables[1], ['beta'] = VersionesBeta[1]}
	end
end

-- Función envoltura para aregar citas en la ficha
function citar(frame, Datos, Grupo)
	if not type(Datos) == table then return '' end
	if type(Grupo) == 'string' then
		Grupo = ' group="' .. Grupo:gsub('|', '{{!}}') .. '"'
	else
		Grupo = ''
	end

	local Salida	= {}
	for k,v in pairs(Datos) do
		table.insert(Salida, k .. '=' .. v)
	end
	
	if next(Salida) then return frame:preprocess('<ref' .. Grupo .. '>{{cita web|' .. table.concat(Salida, '|') .. '}}</ref>') end
end

-- Función, propiedad() personalizada
function propiedad(idPropiedad, opciones, entidad)
	if not entidad then entidad = Entidad end

	if entidad and entidad.claims and entidad.claims[idPropiedad] then
		if not opciones then
			opciones = {['linkback']='sí'}
		end

		local ValorPosicional = 1
		if type(opciones['valor_posicional']) == 'number' then ValorPosicional = opciones['valor_posicional'] end
		
		local ValorPosicionalCalif = 1
		if type(opciones['valor_posicional_calif']) == 'number' then ValorPosicional = opciones['valor_posicional_calif'] end

		local Calificador = opciones['calificador']

		local Obj = elementoTabla(Entidad, 'claims', idPropiedad, ValorPosicional)
		if Calificador then
			Obj = elementoTabla(Obj, 'qualifiers', Calificador, ValorPosicionalCalif)
		else
			Obj = elementoTabla(Obj, 'mainsnak')
		end

		if opciones['formato'] == 'número' then
			if elementoTabla(Obj, 'datavalue', 'type') == 'quantity' then
				return formatoNumero(elementoTabla(Obj, 'mainsnak', 'datavalue', 'value', 'amount'))
			end

		-- Valores cuya unidad deba ir a la derecha, separada de un espacio
		elseif opciones['formato'] == 'unidad' then
			if elementoTabla(Entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue') then
				return formatoNumero(elementoTabla(Entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue', 'value', 'amount')) .. '&nbsp;-&nbsp;' .. numeroUnidad(elementoTabla(Entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue'))
			else
				return numeroUnidad(elementoTabla(Entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue'))
			end
			
		-- Valores cuya unidad deba ir a la izquierda (ej, las monedas o divisas)
		elseif opciones['formato'] == 'moneda' then
			if elementoTabla(Entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue') then
				return numeroUnidad(elementoTabla(Entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue'), false) .. '&nbsp;-&nbsp;' .. numeroUnidad(elementoTabla(Entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue'), false)
			else
				return numeroUnidad(elementoTabla(Entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue'), false)
			end
		
		-- Devolver el ID de la entidad, para propiedades de entidad
		elseif opciones['formato'] == 'entidadID' then
			return elementoTabla(Obj, 'datavalue', 'value', 'id')
		end

		-- Invocar a la función fallback si no se cumplen las condiciones anteriores
		opciones.entityId  = entidad.id
		opciones.propiedad = idPropiedad
		return ModuloWikidata.getPropiedad(opciones,entidad.claims[idPropiedad])
	end
end

return p