Модуль:URL: различия между версиями
Admin (обсуждение | вклад) м 1 версия импортирована |
Check for nested calls. See Template_talk:URL for more details. |
||
| Строка 1: | Строка 1: | ||
function | -- | ||
-- This module implements {{URL}} | |||
return | -- | ||
-- See unit tests at [[Module:URL/testcases]] | |||
local p = {} | |||
local function safeUri(s) | |||
local success, uri = pcall(function() | |||
return mw.uri.new(s) | |||
end) | |||
if success then | |||
return uri | |||
end | end | ||
end | end | ||
local function extractUrl(args) | |||
for name, val in pairs(args) do | |||
function | if name ~= 2 and name ~= "msg" then | ||
local url = name .. "=" .. val; | |||
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3') | |||
local uri = safeUri(url); | |||
if uri and uri.host then | |||
return url | |||
end | end | ||
end | end | ||
end | end | ||
end | |||
function p._url(url, text, msg) | |||
url = mw.text.trim(url or '') | |||
text = mw.text.trim(text or '') | |||
-- Check for pre-formatted url. Catches '{{url|{{url|google.com}}}}' that can occur via template | |||
if (mw.ustring.match(url, '^<span class="url">')) then | |||
return url, text, msg | |||
end | end | ||
local | local nomsg = (msg or ''):sub(1,1):lower() == "n" or msg == 'false' -- boolean: true if msg is "false" or starts with n or N | ||
if | if url == '' then | ||
if text == '' then | |||
if nomsg then | |||
return nil | |||
if | |||
return | |||
else | else | ||
return | return mw.getCurrentFrame():expandTemplate{ title = 'tlx', args = { 'URL', "''example.com''", "''optional display text''" } } | ||
end | end | ||
else | |||
return text | |||
end | end | ||
end | end | ||
-- If the URL contains any unencoded spaces, encode them, because MediaWiki will otherwise interpret a space as the end of the URL. | |||
url = mw.ustring.gsub(url, '%s', function(s) return mw.uri.encode(s, 'PATH') end) | |||
-- If there is an empty query string or fragment id, remove it as it will cause mw.uri.new to throw an error | |||
url = mw.ustring.gsub(url, '#$', '') | |||
url = mw.ustring.gsub(url, '%?$', '') | |||
-- If it's an HTTP[S] URL without the double slash, fix it. | |||
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3') | |||
local uri = safeUri(url) | |||
-- | -- Handle URL's without a protocol and URL's that are protocol-relative, | ||
if | -- e.g. www.example.com/foo or www.example.com:8080/foo, and //www.example.com/foo | ||
if uri and (not uri.protocol or (uri.protocol and not uri.host)) and url:sub(1, 2) ~= '//' then | |||
url = 'http://' .. url | |||
uri = safeUri(url) | |||
end | end | ||
if | if text == '' then | ||
if uri then | |||
if | if uri.path == '/' then uri.path = '' end | ||
end | |||
local port = '' | |||
if uri.port then port = ':' .. uri.port end | |||
text = mw.ustring.lower(uri.host or '') .. port .. (uri.relativePath or '') | |||
-- Add <wbr> before _/.-# sequences | |||
text = mw.ustring.gsub(text,"(/+)","<wbr/>%1") -- This entry MUST be the first. "<wbr/>" has a "/" in it, you know. | |||
text = mw.ustring.gsub(text,"(%.+)","<wbr/>%1") | |||
-- text = mw.ustring.gsub(text,"(%-+)","<wbr/>%1") -- DISABLED for now | |||
text = mw.ustring.gsub(text,"(%#+)","<wbr/>%1") | |||
text = mw.ustring.gsub(text,"(_+)","<wbr/>%1") | |||
else -- URL is badly-formed, so just display whatever was passed in | |||
text = url | |||
end | |||
end | end | ||
return mw.ustring.format('<span class="url">[%s %s]</span>', url, text) | |||
return | |||
end | end | ||
function p. | --[[ | ||
The main entry point for calling from Template:URL. | |||
--]] | |||
function p.url(frame) | |||
local templateArgs = frame.args | |||
local | local parentArgs = frame:getParent().args | ||
local url = templateArgs[1] or parentArgs[1] | |||
local text = templateArgs[2] or parentArgs[2] or '' | |||
local msg = templateArgs.msg or parentArgs.msg or '' | |||
url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or '' | |||
return p._url(url, text, msg) | |||
end | |||
return | --[[ | ||
The entry point for calling from the forked Template:URL2. | |||
This function returns no message by default. | |||
It strips out wiki-link markup, html tags, and everything after a space. | |||
--]] | |||
function p.url2(frame) | |||
local templateArgs = frame.args | |||
local parentArgs = frame:getParent().args | |||
local url = templateArgs[1] or parentArgs[1] | |||
local text = templateArgs[2] or parentArgs[2] or '' | |||
-- default to no message | |||
local msg = templateArgs.msg or parentArgs.msg or 'no' | |||
url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or '' | |||
-- if the url came from a Wikidata call, it might have a pen icon appended | |||
-- we want to keep that and add it back at the end. | |||
local u1, penicon = mw.ustring.match( url, "(.*)( <span class='penicon.*)" ) | |||
if penicon then url = u1 end | |||
-- strip out html tags and [ ] from url | |||
url = (url or ''):gsub("<[^>]*>", ""):gsub("[%[%]]", "") | |||
-- truncate anything after a space | |||
url = url:gsub("%%20", " "):gsub(" .*", "") | |||
return (p._url(url, text, msg) or "") .. (penicon or "") | |||
end | end | ||
return p | return p | ||
Версия от 01:08, 13 ноября 2025
Внимание! Это один из самых используемых модулей.
Этот модуль относится к критическим. У него очень много включений или он используется с подстановкой. Из-за опасности вандализма или ошибочного редактирования он был защищён.
Модуль используется в шаблоне {{URL}}.
Тесты
34 тестов провалено.
| Тест | Ожидаемое значение | Фактическое значение | |
|---|---|---|---|
| Файл:X mark.svg | {{#invoke:URL | formatUrl | }} | Ошибка скрипта: Функции «formatUrl» не существует. | |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | EXAMPLE.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | example.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | www.example.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://www.example.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://пример.рф }} | пример.рф | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | https://www.example.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | ftp://www.example.com }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | ftp://ftp.example.com }} | ftp.example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://www.example.com/ }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | //ftp.example.com }} | ftp.example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | //www.example.com/ }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | www.example.com/foo }} | example.com/foo | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://www.example.com/foo }} | example.com/foo | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://sub.example.com/foo/bar }} | sub.example.com/foo/bar | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | example.com?a }} | example.com?a | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://sub.example.com/foo/bar?a }} | sub.example.com/foo/bar?a | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | example.com | title }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | example.com?a | title }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://sub.example.com/foo/bar | title }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://sub.example.com/foo/bar?a | title }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://example.com] }} | example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://example.com title] }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://пример.рф пример] }} | пример | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://example.com old title] | title }} | title | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | email@example.com }} | email@example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | mailto:email@example.com }} | email@example.com | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://example.com title]{{ref-en}} }} | title (англ.) | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://example.com/very/long/path/index.html | length = 25 }} | example.com/very/long/pa… | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | http://very.long.domain.example.com/index.html | length = 25 }} | very.long.domain.example.com/… | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://very.long.domain.example.com/index.html] | length = 25 }} | very.long.domain.example.com/… | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [https://web.archive.org/web/20070520014853/http://example.com/] | length = 25 }} | web.archive.org/web/2007… | Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [http://example.com example.com]<br>[http://www.example.ru example.ru] }} | example.com example.ru |
Ошибка скрипта: Функции «formatUrl» не существует. |
| Файл:X mark.svg | {{#invoke:URL | formatUrl | [[Site]] }} | Site | Ошибка скрипта: Функции «formatUrl» не существует. |
--
-- This module implements {{URL}}
--
-- See unit tests at [[Module:URL/testcases]]
local p = {}
local function safeUri(s)
local success, uri = pcall(function()
return mw.uri.new(s)
end)
if success then
return uri
end
end
local function extractUrl(args)
for name, val in pairs(args) do
if name ~= 2 and name ~= "msg" then
local url = name .. "=" .. val;
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
local uri = safeUri(url);
if uri and uri.host then
return url
end
end
end
end
function p._url(url, text, msg)
url = mw.text.trim(url or '')
text = mw.text.trim(text or '')
-- Check for pre-formatted url. Catches '{{url|{{url|google.com}}}}' that can occur via template
if (mw.ustring.match(url, '^<span class="url">')) then
return url, text, msg
end
local nomsg = (msg or ''):sub(1,1):lower() == "n" or msg == 'false' -- boolean: true if msg is "false" or starts with n or N
if url == '' then
if text == '' then
if nomsg then
return nil
else
return mw.getCurrentFrame():expandTemplate{ title = 'tlx', args = { 'URL', "''example.com''", "''optional display text''" } }
end
else
return text
end
end
-- If the URL contains any unencoded spaces, encode them, because MediaWiki will otherwise interpret a space as the end of the URL.
url = mw.ustring.gsub(url, '%s', function(s) return mw.uri.encode(s, 'PATH') end)
-- If there is an empty query string or fragment id, remove it as it will cause mw.uri.new to throw an error
url = mw.ustring.gsub(url, '#$', '')
url = mw.ustring.gsub(url, '%?$', '')
-- If it's an HTTP[S] URL without the double slash, fix it.
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
local uri = safeUri(url)
-- Handle URL's without a protocol and URL's that are protocol-relative,
-- e.g. www.example.com/foo or www.example.com:8080/foo, and //www.example.com/foo
if uri and (not uri.protocol or (uri.protocol and not uri.host)) and url:sub(1, 2) ~= '//' then
url = 'http://' .. url
uri = safeUri(url)
end
if text == '' then
if uri then
if uri.path == '/' then uri.path = '' end
local port = ''
if uri.port then port = ':' .. uri.port end
text = mw.ustring.lower(uri.host or '') .. port .. (uri.relativePath or '')
-- Add <wbr> before _/.-# sequences
text = mw.ustring.gsub(text,"(/+)","<wbr/>%1") -- This entry MUST be the first. "<wbr/>" has a "/" in it, you know.
text = mw.ustring.gsub(text,"(%.+)","<wbr/>%1")
-- text = mw.ustring.gsub(text,"(%-+)","<wbr/>%1") -- DISABLED for now
text = mw.ustring.gsub(text,"(%#+)","<wbr/>%1")
text = mw.ustring.gsub(text,"(_+)","<wbr/>%1")
else -- URL is badly-formed, so just display whatever was passed in
text = url
end
end
return mw.ustring.format('<span class="url">[%s %s]</span>', url, text)
end
--[[
The main entry point for calling from Template:URL.
--]]
function p.url(frame)
local templateArgs = frame.args
local parentArgs = frame:getParent().args
local url = templateArgs[1] or parentArgs[1]
local text = templateArgs[2] or parentArgs[2] or ''
local msg = templateArgs.msg or parentArgs.msg or ''
url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
return p._url(url, text, msg)
end
--[[
The entry point for calling from the forked Template:URL2.
This function returns no message by default.
It strips out wiki-link markup, html tags, and everything after a space.
--]]
function p.url2(frame)
local templateArgs = frame.args
local parentArgs = frame:getParent().args
local url = templateArgs[1] or parentArgs[1]
local text = templateArgs[2] or parentArgs[2] or ''
-- default to no message
local msg = templateArgs.msg or parentArgs.msg or 'no'
url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
-- if the url came from a Wikidata call, it might have a pen icon appended
-- we want to keep that and add it back at the end.
local u1, penicon = mw.ustring.match( url, "(.*)( <span class='penicon.*)" )
if penicon then url = u1 end
-- strip out html tags and [ ] from url
url = (url or ''):gsub("<[^>]*>", ""):gsub("[%[%]]", "")
-- truncate anything after a space
url = url:gsub("%%20", " "):gsub(" .*", "")
return (p._url(url, text, msg) or "") .. (penicon or "")
end
return p