Открыть меню
Открыть персональное меню
Вы не представились системе
Your IP address will be publicly visible if you make any edits.

Модуль:Hatnote: различия между версиями

Материал из Энциклопедия Тренерон
ru>Grain of sand
 
м (1 версия импортирована)
 
(не показаны 2 промежуточные версии 2 участников)
Строка 1: Строка 1:
local get_args = require('Module:Arguments').getArgs
--------------------------------------------------------------------------------
local mError
--                              Module:Hatnote                                --
local yesno = function (v) return require('Module:Yesno')(v, true) end
--                                                                            --
-- This module produces hatnote links and links to related articles. It      --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules.                            --
--------------------------------------------------------------------------------


local p, tr = {}, {}
local libraryUtil = require('libraryUtil')
local current_title = mw.title.getCurrentTitle()
local checkType = libraryUtil.checkType
local tracking_categories = {
local mArguments -- lazily initialise [[Module:Arguments]]
no_prefix = 'Википедия:Страницы с модулем Hatnote без указания префикса',
local yesno -- lazily initialise [[Module:Yesno]]
no_links = 'Википедия:Страницы с модулем Hatnote без ссылок',
red_link = 'Википедия:Страницы с модулем Hatnote с красной ссылкой',
bad_format = 'Википедия:Страницы с модулем Hatnote с некорректно заполненными параметрами',
unparsable_link = 'Википедия:Страницы с модулем Hatnote с нечитаемой ссылкой',
formatted = 'Википедия:Страницы с модулем Hatnote с готовым форматированием',
}


local function index(t1, t2)
local p = {}
return setmetatable(t1, {__index = t2})
 
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
 
local function getArgs(frame)
    -- Fetches the arguments from the parent frame. Whitespace is trimmed and
    -- blanks are removed.
    mArguments = require('Module:Arguments')
    return mArguments.getArgs(frame, {parentOnly = true})
end
end


local function concat(e1, e2)
local function removeInitialColon(s)
return tostring(e1) .. tostring(e2)
    -- Removes the initial colon from a string, if present.
    return s:match('^:?(.*)')
end
end


function tr.define_categories(tracked_cases)
function p.defaultClasses(inline)
local categories = setmetatable({}, {
    -- Provides the default hatnote classes as a space-separated string; useful
__tostring = function (self) return table.concat(self) end,
    -- for hatnote-manipulation modules like [[Module:Hatnote group]].
__concat = concat
    return
})
    (inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
            'navigation-not-searchable'
end


function categories:add(element, nocat)
function p.disambiguate(page, disambiguator)
if not nocat then
    -- Formats a page title with a disambiguation parenthetical,
local cat_name
    -- i.e. "Example" → "Example (disambiguation)".
if tracked_cases and tracked_cases[element] then
    checkType('disambiguate', 1, page, 'string')
cat_name = tracked_cases[element]
    checkType('disambiguate', 2, disambiguator, 'string', true)
else
    disambiguator = disambiguator or 'disambiguation'
cat_name = element
    return mw.ustring.format('%s (%s)', page, disambiguator)
end
table.insert(self, string.format('[[Категория:%s]]', cat_name))
end
end
return categories
end
end


function tr.error(msg, categories, preview_only)
function p.findNamespaceId(link, removeColon)
local current_frame = mw.getCurrentFrame()
    -- Finds the namespace id (namespace number) of a link or a pagename. This
local parent_frame = current_frame:getParent()
    -- function will not work if the link is enclosed in double brackets. Colons
local res_frame_title = parent_frame and parent_frame:getTitle() ~= current_title.prefixedText and
    -- are trimmed from the start of the link by default. To skip colon
parent_frame:getTitle() or
    -- trimming, set the removeColon parameter to false.
current_frame:getTitle()
    checkType('findNamespaceId', 1, link, 'string')
if not preview_only or current_frame:preprocess('{{REVISIONID}}') == '' then
    checkType('findNamespaceId', 2, removeColon, 'boolean', true)
mError = require('Module:Error')
    if removeColon ~= false then
return mError.error{
        link = removeInitialColon(link)
tag = 'div',
    end
string.format('Ошибка в [[%s]]: %s.'
    local namespace = link:match('^(.-):')
.. (preview_only and '<br><small>Это сообщение показывается только во время предпросмотра.</small>' or ''), res_frame_title, msg)
    if namespace then
} .. categories
        local nsTable = mw.site.namespaces[namespace]
else
        if nsTable then
return categories
            return nsTable.id
end
        end
    end
    return 0
end
end


function p.parse_link(frame)
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
local args = get_args(frame)
    -- Formats an error message to be returned to wikitext. If
local link = args[1]:gsub('\n', '')
    -- addTrackingCategory is not false after being returned from
local label
    -- [[Module:Yesno]], and if we are not on a talk page, a tracking category
    -- is added.
link = mw.text.trim(link:match('^%[%[([^%]]+)%]%]$') or link)
    checkType('makeWikitextError', 1, msg, 'string')
if link:sub(1, 1) == '/' then
    checkType('makeWikitextError', 2, helpLink, 'string', true)
label = link
    yesno = require('Module:Yesno')
link = current_title.prefixedText .. link
    title = title or mw.title.getCurrentTitle()
end
    -- Make the help link text.
link = link:match(':?(.+)')
    local helpText
if link:match('|') then
    if helpLink then
link, label = link:match('^([^%|]+)%|(.+)$')
        helpText = ' ([[' .. helpLink .. '|help]])'
end
    else
        helpText = ''
if not mw.title.new(link) then
    end
return nil, nil
    -- Make the category text.
end
    local category
    if not title.isTalkPage -- Don't categorise talk pages
return link, label
            and title.namespace ~= 2 -- Don't categorise userspace
            and yesno(addTrackingCategory) ~= false -- Allow opting out
    then
        category = 'Hatnote templates with errors'
        category = mw.ustring.format(
                '[[%s:%s]]',
                mw.site.namespaces[14].name,
                category
        )
    else
        category = ''
    end
    return mw.ustring.format(
            '<strong class="error">Error: %s%s.</strong>%s',
            msg,
            helpText,
            category
    )
end
end


function p.format_link(frame)
local curNs = mw.title.getCurrentTitle().namespace
-- {{ссылка на раздел}}
p.missingTargetCat =
local args = get_args(frame)
--Default missing target category, exported for use in related modules
local link, section, label = args[1], args[2], args[3]
((curNs == 0) or (curNs == 14)) and
        'Articles with hatnote templates targeting a nonexistent page' or nil
if not link then
link = current_title.prefixedText
if section then
link = '#' .. section
label = label or '§&nbsp;' .. section
end
else
local parsed_link, parsed_label = p.parse_link{link}
if parsed_link then
link = parsed_link
else
return link
end
if section and not link:match('#') then
link = link .. '#' .. section
if parsed_label then
parsed_label = parsed_label .. '#' .. section
end
end
label = (label or parsed_label or link):gsub('^([^#]-)#(.+)$', '%1 §&nbsp;%2')
end
if label and label ~= link then
return string.format('[[:%s|%s]]', link, label)
else
return string.format('[[:%s]]', link)
end
end


function p.remove_precision(frame)
function p.quote(title)
-- {{без уточнения}}
    --Wraps titles in quotation marks. If the title starts/ends with a quotation
local args = get_args(frame)
    --mark, kerns that side as with {{-'}}
local title = args[1]
    local quotationMarks = {
        ["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
return title:match('^(.+)%s+%b()$') or title
    }
    local quoteLeft, quoteRight = -- Test if start/end are quotation marks
    quotationMarks[string.sub(title,  1,  1)],
    quotationMarks[string.sub(title, -1, -1)]
    if quoteLeft or quoteRight then
        title = mw.html.create("span"):wikitext(title)
    end
    if quoteLeft  then title:css("padding-left",  "0.15em") end
    if quoteRight then title:css("padding-right", "0.15em") end
    return '"' .. tostring(title) .. '"'
end
end


function p.is_disambig(frame)
--------------------------------------------------------------------------------
local args = get_args(frame)
-- Hatnote
local title = args[1]
--
local page = mw.title.new(title)
-- Produces standard hatnote text. Implements the {{hatnote}} template.
--------------------------------------------------------------------------------
if not page or not page.exists or mw.title.equals(page, current_title) then
return false
end
local page_content = page:getContent()
local mw_list_content = mw.title.new('MediaWiki:Disambiguationspage'):getContent()
local lang = mw.language.getContentLanguage()
for template in mw.ustring.gmatch(mw_list_content, '%*%s?%[%[Шаблон:([^%]]+)') do
if page_content:match('{{' .. template) or page_content:match('{{' .. lang:lcfirst(template)) then
return true
end
end
return false
end


function p.list(frame)
local function decorateHatnote(hatnote, options)
local args = get_args(frame, {trim = false})
    local function getIcon(filename)
local list_sep = args.list_sep or args['разделитель списка'] or ', '
        local html = ''
local last_list_sep = yesno(args.natural_join) ~= false and ' и ' or list_sep
        if type(filename) == 'string' then
local links_ns = args.links_ns or args['ПИ ссылок']
            local icon = mw.html.create('span')
local bold_links = yesno(args.bold_links or args['ссылки болдом'])
            icon
                    :addClass('hatnote-icon')
                    :addClass('metadata')
                    :wikitext('[[File:' .. filename .. '|14px|link=]]')
                    :done()
            html = tostring(icon)
        end
        return html
    end


local res_list = {}
    local container = mw.html.create('div')
local tracked = {
    container
red_link = false,
            :addClass('hatnote-container')
bad_format = false,
            :wikitext(getIcon(options.icon))
formatted = false,
            :wikitext(tostring(hatnote))
unparsable_link = false
            :done()
}
    return container
local i = 1
while args[i] do
local link = args[i]
local label = args['l' .. i]
local element = ''
if link:match('<span') then -- TODO: переписать
tracked.formatted = true
element = link -- for {{не переведено}}
else
local bad_format = (link:match('|') or link:match('[%[%]]')) ~= nil
local parsed_link, parsed_label = p.parse_link{link}
if parsed_link then
tracked.bad_format = tracked.bad_format or bad_format
if links_ns then
parsed_label = parsed_label or parsed_link
parsed_link = mw.site.namespaces[links_ns].name .. ':' .. parsed_link
end
local title = mw.title.new(parsed_link)
tracked.red_link = tracked.red_link or not (title.isExternal or title.exists)
element = p.format_link{parsed_link, nil, label or parsed_label}
else
tracked.unparsable_link = true
element = link
end
end
if bold_links then
element = string.format('<b>%s</b>', element)
end
table.insert(res_list, element)
i = i + 1
end
return setmetatable(res_list, {
__index = tracked,
__tostring = function (self) return mw.text.listToText(self, list_sep, last_list_sep) end,
__concat = concat,
__pairs = function (self) return pairs(tracked) end
})
end
end


function p.hatnote(frame)
function p.hatnote(frame)
local args = get_args(frame)
    local args = getArgs(frame)
local text = args[1]
    local s = args[1]
local id = args.id
    if not s then
local extraclasses = args.extraclasses
        return p.makeWikitextError(
local hide_disambig = yesno(args.hide_disambig)
                'no text specified',
                'Template:Hatnote#Errors',
local res = mw.html.create('div')
                args.category
:attr('id', id)
        )
:addClass('hatnote')
    end
:addClass('navigation-not-searchable')
    return p._hatnote(s, {
:addClass(extraclasses)
        extraclasses = args.extraclasses,
:wikitext(text)
        selfref = args.selfref
    })
if hide_disambig then
res:addClass('dabhide')
end
return res
end
end


function p.main(frame, _tracking_categories)
function p._hatnote(s, options)
local args = get_args(frame, {trim = false})
    checkType('_hatnote', 1, s, 'string')
    checkType('_hatnote', 2, options, 'table', true)
local prefix = args.prefix or args['префикс']
    options = options or {}
local prefix_plural = args.prefix_plural or args['префикс мн. ч.']
    local inline = options.inline
local sep = args.sep or args['разделитель'] or ' '
    local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
local dot = yesno(args.dot or args['точка']) and '.' or ''
    local extraclasses
local nocat = yesno(args.nocat)
    if type(options.extraclasses) == 'string' then
local preview_error = yesno(args.preview_error)
        extraclasses = options.extraclasses
local empty_list_message = args.empty_list_message or 'Не указано ни одной страницы'
    end
 
categories = tr.define_categories(index(_tracking_categories or {}, tracking_categories))
    hatnote
            :attr('role', 'note')
            :addClass(p.defaultClasses(inline))
            :addClass(extraclasses)
            :addClass(options.selfref and 'selfref' or nil)
            :wikitext(s)
 
    -- Decorate WP hatnote to SCW standard
    hatnote = decorateHatnote(hatnote, options)


if not prefix then
    return mw.getCurrentFrame():extensionTag{
categories:add('no_prefix', nocat)
        name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
return tr.error('Не указан префикс', categories)
    } .. tostring(hatnote)
end
if not args[1] then
categories:add('no_links', nocat)
return tr.error(empty_list_message, categories, preview_error)
end
if args[2] and prefix_plural then
prefix = prefix_plural
end
local list = p.list(args)
for k, v in pairs(list) do
if type(v) == 'boolean' and v then
categories:add(k, nocat)
end
end
return p.hatnote(index({prefix .. sep .. list .. dot}, args)) .. categories
end
end


return index(p, tr)
return p

Текущая версия от 09:52, 24 октября 2023

Для документации этого модуля может быть создана страница Модуль:Hatnote/doc

--------------------------------------------------------------------------------
--                              Module:Hatnote                                --
--                                                                            --
-- This module produces hatnote links and links to related articles. It       --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules.                            --
--------------------------------------------------------------------------------

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]

local p = {}

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

local function getArgs(frame)
    -- Fetches the arguments from the parent frame. Whitespace is trimmed and
    -- blanks are removed.
    mArguments = require('Module:Arguments')
    return mArguments.getArgs(frame, {parentOnly = true})
end

local function removeInitialColon(s)
    -- Removes the initial colon from a string, if present.
    return s:match('^:?(.*)')
end

function p.defaultClasses(inline)
    -- Provides the default hatnote classes as a space-separated string; useful
    -- for hatnote-manipulation modules like [[Module:Hatnote group]].
    return
    (inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
            'navigation-not-searchable'
end

function p.disambiguate(page, disambiguator)
    -- Formats a page title with a disambiguation parenthetical,
    -- i.e. "Example" → "Example (disambiguation)".
    checkType('disambiguate', 1, page, 'string')
    checkType('disambiguate', 2, disambiguator, 'string', true)
    disambiguator = disambiguator or 'disambiguation'
    return mw.ustring.format('%s (%s)', page, disambiguator)
end

function p.findNamespaceId(link, removeColon)
    -- Finds the namespace id (namespace number) of a link or a pagename. This
    -- function will not work if the link is enclosed in double brackets. Colons
    -- are trimmed from the start of the link by default. To skip colon
    -- trimming, set the removeColon parameter to false.
    checkType('findNamespaceId', 1, link, 'string')
    checkType('findNamespaceId', 2, removeColon, 'boolean', true)
    if removeColon ~= false then
        link = removeInitialColon(link)
    end
    local namespace = link:match('^(.-):')
    if namespace then
        local nsTable = mw.site.namespaces[namespace]
        if nsTable then
            return nsTable.id
        end
    end
    return 0
end

function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
    -- Formats an error message to be returned to wikitext. If
    -- addTrackingCategory is not false after being returned from
    -- [[Module:Yesno]], and if we are not on a talk page, a tracking category
    -- is added.
    checkType('makeWikitextError', 1, msg, 'string')
    checkType('makeWikitextError', 2, helpLink, 'string', true)
    yesno = require('Module:Yesno')
    title = title or mw.title.getCurrentTitle()
    -- Make the help link text.
    local helpText
    if helpLink then
        helpText = ' ([[' .. helpLink .. '|help]])'
    else
        helpText = ''
    end
    -- Make the category text.
    local category
    if not title.isTalkPage -- Don't categorise talk pages
            and title.namespace ~= 2 -- Don't categorise userspace
            and yesno(addTrackingCategory) ~= false -- Allow opting out
    then
        category = 'Hatnote templates with errors'
        category = mw.ustring.format(
                '[[%s:%s]]',
                mw.site.namespaces[14].name,
                category
        )
    else
        category = ''
    end
    return mw.ustring.format(
            '<strong class="error">Error: %s%s.</strong>%s',
            msg,
            helpText,
            category
    )
end

local curNs = mw.title.getCurrentTitle().namespace
p.missingTargetCat =
--Default missing target category, exported for use in related modules
((curNs ==  0) or (curNs == 14)) and
        'Articles with hatnote templates targeting a nonexistent page' or nil

function p.quote(title)
    --Wraps titles in quotation marks. If the title starts/ends with a quotation
    --mark, kerns that side as with {{-'}}
    local quotationMarks = {
        ["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
    }
    local quoteLeft, quoteRight = -- Test if start/end are quotation marks
    quotationMarks[string.sub(title,  1,  1)],
    quotationMarks[string.sub(title, -1, -1)]
    if quoteLeft or quoteRight then
        title = mw.html.create("span"):wikitext(title)
    end
    if quoteLeft  then title:css("padding-left",  "0.15em") end
    if quoteRight then title:css("padding-right", "0.15em") end
    return '"' .. tostring(title) .. '"'
end

--------------------------------------------------------------------------------
-- Hatnote
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
--------------------------------------------------------------------------------

local function decorateHatnote(hatnote, options)
    local function getIcon(filename)
        local html = ''
        if type(filename) == 'string' then
            local icon = mw.html.create('span')
            icon
                    :addClass('hatnote-icon')
                    :addClass('metadata')
                    :wikitext('[[File:' .. filename .. '|14px|link=]]')
                    :done()
            html = tostring(icon)
        end
        return html
    end

    local container = mw.html.create('div')
    container
            :addClass('hatnote-container')
            :wikitext(getIcon(options.icon))
            :wikitext(tostring(hatnote))
            :done()
    return container
end

function p.hatnote(frame)
    local args = getArgs(frame)
    local s = args[1]
    if not s then
        return p.makeWikitextError(
                'no text specified',
                'Template:Hatnote#Errors',
                args.category
        )
    end
    return p._hatnote(s, {
        extraclasses = args.extraclasses,
        selfref = args.selfref
    })
end

function p._hatnote(s, options)
    checkType('_hatnote', 1, s, 'string')
    checkType('_hatnote', 2, options, 'table', true)
    options = options or {}
    local inline = options.inline
    local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
    local extraclasses
    if type(options.extraclasses) == 'string' then
        extraclasses = options.extraclasses
    end

    hatnote
            :attr('role', 'note')
            :addClass(p.defaultClasses(inline))
            :addClass(extraclasses)
            :addClass(options.selfref and 'selfref' or nil)
            :wikitext(s)

    -- Decorate WP hatnote to SCW standard
    hatnote = decorateHatnote(hatnote, options)

    return mw.getCurrentFrame():extensionTag{
        name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
    } .. tostring(hatnote)
end

return p