Vorlagenprogrammierung Diskussionen Lua Unterseiten
Modul Deutsch

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


--[=[ Version: 2022-11-25
	URL-Object
	Author: Vollbracht
Constructor: URL:new(<external link string>)
Fields:
	full:		addressable link string as given in new() parameter
	protocol:	(optional, default: empty) http, ftp, etc.
	server:		(optional, default: empty) de, www, www2, etc.; access default
				server (for https e.g.) at given site if void
	domain:		(mandantory) dns portion of a link string: wikipedia.org e. g.
	TLD:		most significant part of domain
	subdomain:	domain portion (least significant parts only)
	path:		(optional, default: empty, i. e. www root for https e. g.)
				/wiki or /wiki/Wikipedia:Lua/Modul/Wikidata/Time e. g.
	file:		(optional, default: empty, i. e. index.html e. g. depending on
				server configuration) index.php e. g.
	parameters:	(optional, default: empty) portion after ?:
				title=Modul:URL&action=edit&redlink=1 e. g.
	portion:	(optional, default: empty, not in combination with parameters)
				#chapter_5 e.g.
methods:
	relative()	new URL object ### still to be implemented
]=]

-- extend following TLDs to 2nd level: (com.tw is TLD. com.de is not.)
local eTLDs = {'tw', 'uk'}

service = {
	--[[
		URL:toString()
		standard method representing the content
	]]
	toString = function(this)
		return this.full
	end,
	--[[
		URL:short()
		link to full URL address with label reduced to domain as of NIC
	]]
	short = function(this)
		--return '<a href="' .. this.full .. '">' .. this.domain .. '</a>'
		return '[' .. this.full .. ' ' .. this.domain .. ']'
	end,
	--[[
		URL:format(property)
		format link to convenient label
		parameters:
			property	either a known property of a URL as listed above or a
						format string delimiting link label by angle brackets
						or nothing but a label string
		returns:	link to full URL address with label as given by property
	]]
	format = function(this, property)
		local pre, fmt, post = property:match('(.-)(<.*>)(.*)')
		if fmt then
			for k, v in pairs(this) do
				local s, e = fmt:find('<'.. k .. '>')
				if s then
					if e then
						fmt = fmt:sub(1, s - 1) .. v .. fmt:sub(e+1)
					else
						fmt = fmt:sub(1, s - 1) .. v
					end
				end
			end
			if not pre then pre = '' end
			if not post then post = '' end
			return pre .. '[' .. this.full .. ' ' .. fmt .. ']' .. post
		end
		if this[property] then
			return '[' .. this.full .. ' ' .. this[property] .. ']'
		end
		return '[' .. this.full .. ' ' .. property .. ']'
	end
}

--[[
	URL:new()
]]
function service:new(link)
	if not link then return nil end
	local result = {}
	if type(link) == "string" then
		result.full = link:match('^%S+')
		if not result.full then return nil end
		local i = result.full:find('://', nil, true)
		if i then
			result.protocol = result.full:sub(1, i-1)
			link = link:sub(i+3)
		end
		i = link:find('%/')
		local file = ''
		if i then
			if i < 3 then return nil end
			result.server = link:sub(1, i-1)
			link = link:sub(i+1)
			i = link:find('?', nil, true)
			if i then
				result.params = link:sub(i+1)
				result.file = '/' .. link:sub(1, i-1)
			else
				i = link:find('#')
				if i then
					result.portion = link:sub(i+1)
					result.file = '/' .. link:sub(1, i-1)
				else
					result.file = '/' .. link
				end
			end
		else
			i = link:find('?', nil, true)
			if i then
				if i < 3 then return nil end
				result.params = link:sub(i+1)
				result.server = link:sub(1, i-1)
			else
				i = link:find('#')
				if i then
					if i < 3 then return nil end
					result.portion = link:sub(i+1)
					result.server = link:sub(1, i-1)
				else
					if #link < 2 then return nil end
					result.server = link
				end
			end
		end
		local DNPs = mw.text.split(result.server, '%.')
		if not DNPs[2] then return nil
		else
			local TLDi = #DNPs
			result.TLD = DNPs[#DNPs]
			for _, eTLD in ipairs(eTLDs) do
				if eTLD == result.TLD then
					if TLDi == 2 then return nil end
					TLDi = TLDi - 1
					result.TLD = DNPs[TLDi] .. '.' .. result.TLD
					break
				end
			end
			if TLDi == 2 then
				result.domain = result.server
			else
				result.serverName = DNPs[1]
				result.domain = DNPs[TLDi - 1] .. '.' .. result.TLD
				if TLDi > 3 then
					i = 3
					result.subdomain = DNPs[2]
					while i < TLDi-2 do
						result.subdomain = result.subdomain .. '.' .. DNPs[i]
						i = i + 1
					end
				end
			end
		end
	elseif type(link) == 'table' then
		if not link.domain then return nil end
		result = link
		if not link.full then
			link.full = ''
			if link.protocol then
				result.full = link.protocol .. '://'
			end
			if link.server then result.full = result.full .. link.server
			else
				if link.serverName then
					result.full = result.full .. link.serverName .. '.'
					if link.subdomain then
						result.full = result.full .. link.subdomain .. '.'
					end
				end
				result.full = result.full .. link.domain
			end
			if link.file then result.full = result.full .. link.file end
			if link.parameters then
				result.full = result.full .. '?' .. link.parameters
			elseif link.portion then
				result.full = result.full .. '#' .. link.portion
			end
		end
	else
		return nil
	end
	setmetatable(result, self)
	self.__index = self
	return result
end

service.testFormat = function(frame)
	local u = service:new(frame.args.url)
	return u:format(frame.args.fmtStr)
end

service.test = function(frame)
	local p = frame.args[1]
	if not p then
		p = ''
		for k, v in pairs(frame.args) do
			p = p .. k .. '=' .. v
		end
	end
	local u = service:new(p)
	mw.logObject(u, 'test (URL)')
	return u:short()
end

return service