Модуль:Вложенный список (Bk;rl,&Flk'yuudw vhnvkt)
Перейти к навигации
Перейти к поиску
Этот модуль оценён как готовый к использованию. Предполагается, что все баги устранены и он готов для широкого использования. Его можно указывать на справочных страницах и рекомендовать к использованию новым участникам. Для его изменения и тестирования, пожалуйста, используйте песочницу. |
Данный модуль реализует шаблон {{Вложенный список}}. После перехода на модуль стало возможно заменить старый код шаблона на более доступный и семантичный и начать отслеживать ошибки в коде выводимых страниц.
Код вызова модуля: {{#invoke:Вложенный список|main}}
.
Категории
[[Категория:Википедия:Страницы с ошибками шаблона Вложенный список]] — ставится в случаях:
- несуществования страницы или отсутствия текста при попытке вставить вложенный список (например, в случае некорректной разметки в нём).
- наличия технических ошибок «Медиавики» в выводе вложенного списка.
- наличия в выводе шаблонов:
- {{неоднозначность}}
- {{ФИО}} и аналогичных
- {{К переименованию}} и аналогичных.
- {{TOC right}} и аналогичных.
- {{примечания}}
- ошибок в разметке списков с точки зрения вики-кода и доступности:
- начала вложенного списка не с разметки элемента списка
*
. - вложенных списков с неправильной вложенностью (через
:*
или с**
или с;
в начале).
- начала вложенного списка не с разметки элемента списка
- вложенных списков с заголовками 1-го и 2-го уровня (
==
) в выводе. - вложенных списков с вертикальной чертой (
----
) в выводе. - вложенных списков, в которых вложенные списки не входят в подсписки (
{{NL|Пример}}
вместо* {{NL|Пример}}
).
[[Категория:Википедия:Страницы с шаблоном Вложенный список без ссылок]] ставится в случаях, когда в коде вложенного списка нет ссылок на другие страницы.
require( 'strict' )
--
-- Implements {{Вложенный список}} in one module
-- Allows us to potentially move towards a more accessible markup for the template when the time is right
-- Previously, the template broke the lists {{Вложенный список}} or {{NL2}} or {{NL3}} are in
-- Heavily borrows from https://en.wikipedia.org/wiki/Module:Excerpt_slideshow
--
local getArgs = require( 'Module:Arguments' ).getArgs
local templatePageName = 'Вложенный список'
local modulePageName = 'Вложенный список'
local disambigPageSuffix = ' (значения)'
local editLinkText = 'править'
local errorCat = 'Википедия:Страницы с ошибками шаблона Вложенный список'
-- Remove the variable to stop tracking this category
local linklessCat = 'Википедия:Страницы с шаблоном Вложенный список без ссылок'
local noTitle = 'Нет названия страницы.'
local invalidTitle = 'Неправильное название страницы <code>%s</code>.'
local noContent = 'Ошибка при включении страницы «[[%s]]».'
local noLinks = 'На странице «[[%s]]» нет ссылок на другие страницы.'
local notDisambig = 'На странице «[[%s]]» находится статья.'
-- Adds a replacement to a redirected variant when substed
local substWithRedirects = true
local moduleInvocationCode = '{{#invoke:' .. modulePageName .. '|main|'
local p = {}
local function isEmpty( str )
return str == nil or str == ''
end
local function addWarning( title, message )
if title ~= nil and message == nil then
message = string.format( noContent, title )
end
if title ~= nil and message ~= nil then
message = string.format( message, title )
end
mw.addWarning( string.format( '[[Template:%s|%s]]: %s', templatePageName, templatePageName, message ) )
end
local function templatePattern( str )
return string.format(
"[%s%s]%s",
mw.ustring.upper( mw.ustring.sub( str, 1, 1 ) ),
mw.ustring.lower( mw.ustring.sub( str, 1, 1 ) ),
mw.ustring.gsub( str, '^.', '' )
)
end
local function checkForErrors( sublist )
return mw.ustring.find( sublist, 'class="error' ) ~= nil
-- Templates that should not be there
or mw.ustring.find( sublist, 'id="disambig"' ) ~= nil -- {{disambig}}
or mw.ustring.find( sublist, 'class="hatnote' ) ~= nil -- {{hatnote}}
or mw.ustring.find( sublist, ' ambox ambox-' ) ~= nil -- {{ambox}}
or mw.ustring.find( sublist, '__TOC__' ) ~= nil -- __TOC__
or mw.ustring.find( sublist, 'UNIQ--references' ) ~= nil -- {{references}}
-- Incorrect list markup
or mw.ustring.find( sublist, '^%s*%*' ) ~= 1 -- does not start with a list
or mw.ustring.find( sublist, '^%s*%*%*' ) ~= nil
or mw.ustring.find( sublist, '\n%:%*' ) ~= nil
-- Other incorrect markup
or mw.ustring.find( sublist, '\n;%s*[А-ЯA-Z]' ) ~= nil -- incorrect bold text markup
or mw.ustring.find( sublist, '\n=[^=]' ) ~= nil -- 1st level heading
or mw.ustring.find( sublist, '\n==[^=]' ) ~= nil -- 2nd level heading
or mw.ustring.find( sublist, '\n%-%-%-%-' ) ~= nil -- contains ---- in code
or mw.ustring.find( sublist, '\n<div class="ts%-NL">' ) ~= nil -- {{NL}} after a line break
end
local function getEditLink( title, useRedirect )
local mwTitle = mw.title.new( title )
-- Handle redirects here because it affects action=edit link
if useRedirect ~= true and mwTitle.redirectTarget ~= false then
mwTitle = mwTitle.redirectTarget
end
local span = mw.html.create( 'span' )
:addClass( 'ts-NL-edit mw-editsection-like plainlinks noprint navigation-not-searchable group-user-show' )
:wikitext( string.format(
'<span class="mw-editsection-bracket">[</span>[%s %s]<span class="mw-editsection-bracket">]</span>',
mwTitle:fullUrl( 'action=edit' ),
editLinkText
) )
return tostring( span )
end
local function getError( title, msg, setCategory )
if setCategory == nil then
setCategory = true
end
local errorText = msg
if title ~= nil and title ~= '' then
errorText = string.format( msg, title )
end
addWarning( nil, errorText )
return '<div class="error">' .. errorText .. '</div>'
.. ( setCategory and string.format( '[[Category:%s]]', errorCat ) or '' )
end
-- Prevent template loop by replacing template calls to the calls to this module
local function replaceSubtemplates( content )
if isEmpty( content ) then
return content
end
content = mw.ustring.gsub( content, '{{' .. templatePattern( templatePageName ) .. '/?|', '{{NL|' )
content = mw.ustring.gsub( content, '{{' .. templatePattern( 'NL' ) .. '[23]?%|', moduleInvocationCode )
return content
end
--[[
@param {String} wikitext: Wikitext of just the list (i.e. each line is a list item)
@param {String} symbol: Special character used in the wikitext markup for the list, e.g. '*' or '#'
@param {String} outerTag: Text portion of the tag for each list or sublist, e.g. 'ul' or 'ol'
@param {String} innerTag: Text portion of the tag for each list item, e.g. 'li'
]]
local wikitextToHtmlList = function( wikitext, symbol, outerTag, innerTag )
local listParts = {}
for level, item in mw.ustring.gmatch( '\n' .. wikitext .. '\n', '\n(%' .. symbol .. '+)(.-)%f[\n]' ) do
table.insert( listParts, { level=level, item=item } )
end
table.insert( listParts, { level='', item='' } )
local htmlList = {}
for i, this in ipairs( listParts ) do
local isFirstItem = ( i == 1 )
local isLastItem = ( i == #listParts )
local lastLevel = isFirstItem and '' or listParts[ i - 1 ][ 'level' ]
local tags
if #lastLevel == #this.level then
tags = '</'..innerTag..'><'..innerTag..'>'
elseif #this.level > #lastLevel then
tags = string.rep( '<'..outerTag..'><'..innerTag..'>', #this.level - #lastLevel )
elseif isLastItem then
tags = string.rep( '</'..innerTag..'></'..outerTag..'>', #lastLevel )
else -- ( #this.level < #lastLevel ) and not last item
tags = string.rep( '</'..innerTag..'></'..outerTag..'>', #lastLevel - #this.level ) .. '</'..innerTag..'><'..innerTag..'>'
end
table.insert( htmlList, tags .. this.item )
end
return table.concat( htmlList )
end
--[[
@param {String} wikitext: Wikitext excertp containg zero or more lists
@param {String} symbol: Special character used in the wikitext markup for the list, e.g. '*' or '#'
@param {String} outerTag: Text portion of the tag for each list or sublist, e.g. 'ul' or 'ol'
@param {String} innerTag: Text portion of the tag for each list item, e.g. 'li'
]]
local gsubWikitextLists = function( wikitext, symbol, outerTag, innerTag )
-- temporarily remove list linebreaks...
wikitext = mw.ustring.gsub( wikitext .. '\n', '\n%' .. symbol, '¿¿¿' .. symbol )
-- ...so we can grab the whole list (and just the list)...
return mw.ustring.gsub(
wikitext,
'¿¿¿%'..symbol..'[^\n]+',
function( listWikitext )
-- ...and then reinstate linebreaks...
listWikitext = mw.ustring.gsub( listWikitext, '¿¿¿%' .. symbol, '\n' .. symbol )
-- ...and finally do the conversion
return wikitextToHtmlList( listWikitext, symbol, outerTag, innerTag )
end
)
end
-- Protects the templates from substitution by substituting them with their own parameters
function p._substing( frame )
local args = getArgs( frame, {
parentOnly = true,
} )
local mTemplateInvocation = require( 'Module:Template invocation' )
local name = mTemplateInvocation.name( frame:getParent():getTitle() )
if substWithRedirects then
name = mw.ustring.gsub( name, 'Вложенный список/?', 'NL' )
end
return mTemplateInvocation.invocation( name, args )
end
function p.main( frame )
if mw.isSubsting() then
return p._substing( frame )
end
local args = getArgs( frame )
local title = args[ 1 ]
local displayedTitle = args[ 2 ] or ''
local colon = ':'
local appendedText = args[ 3 ] or ''
if not isEmpty( appendedText ) then
colon = ''
appendedText = ' ' .. appendedText .. ':'
end
local currentTitle = mw.title.getCurrentTitle()
if isEmpty( title ) then
return getError( nil, noTitle, currentTitle.namespace == 0 )
end
-- Render a disambig page name without its bracketed suffix
if displayedTitle == '' and mw.ustring.find( title, disambigPageSuffix, 1, true ) ~= nil then
displayedTitle = mw.ustring.gsub( title, '^%s*(.+)%s+%b()%s*$', '%1' )
end
if displayedTitle ~= '' then
displayedTitle = '|' .. displayedTitle
end
local intro = string.format(
'<span class="dabhide">[[%s%s]]%s</span>%s',
title,
displayedTitle,
colon,
appendedText
)
-- frame:expandTemplate is used because mw.title:getContent() does not handle redirects
local titleObj = mw.title.new( title )
-- Invalid title
if titleObj == nil then
return getError( title, invalidTitle )
end
if titleObj.exists and titleObj.isRedirect then
titleObj = titleObj.redirectTarget
end
-- The page does not exist, equal to current or returns empty
if titleObj.exists ~= true or mw.title.equals( titleObj, currentTitle ) then
return intro .. getEditLink( title, true ) .. getError( title, noContent )
end
local content = titleObj:getContent()
content = replaceSubtemplates( content )
local sublist = frame:preprocess( content )
if mw.text.trim( sublist ) == '' then
return intro .. getEditLink( title, true ) .. getError( title, noContent )
end
-- Reject transclusions that look like articles
if mw.ustring.find( sublist, ' class="infobox' ) ~= nil
or mw.ustring.find( sublist, ' class="navbox' ) ~= nil then
return intro .. getEditLink( title, true ) .. getError( title, notDisambig )
end
intro = intro .. getEditLink( title )
-- Remove 3rd+ level subheadings for easier section insertion (before error checks)
sublist = mw.ustring.gsub( sublist, '\n(===+)(.-)%1\n-', '' )
-- Check sublist for wikitext markup errors
local hasErrors = checkForErrors( sublist )
-- Test if the included page has links
local hasInvocation, invocationPos = mw.ustring.find( content, moduleInvocationCode )
local hasLinks = mw.ustring.find( content, '%*%s*\'*["«„]?\'*%[%[' )
-- Two module invocations mean two different links
or ( hasInvocation and mw.ustring.find( content, moduleInvocationCode, invocationPos ) )
-- [[Модуль:Не переведено]]
or mw.ustring.find( sublist, ' версия статьи «' )
or mw.ustring.find( sublist, 'title="Элемент статьи «' )
-- Replace list markers with HTML list openers
sublist = gsubWikitextLists( '\n' .. sublist, '*', 'ul', 'li' )
sublist = gsubWikitextLists( '\n' .. sublist, '#', 'ol', 'li' )
-- Remove the bold text around links automatically
sublist = mw.ustring.gsub( sublist, "<li>%s*'''%s*%[%[([^%]]+)%]%]%s*'''", '<li>[[%1]]' )
-- Trim and replace double line breaks to avoid breaking the list
sublist = mw.text.trim( sublist )
sublist = mw.ustring.gsub( sublist, '\n\n', '<p>' )
-- Merge adjacent lists
sublist = mw.ustring.gsub( sublist, '</ul>\n-<ul>', '' )
-- Replace remaining
sublist = mw.ustring.gsub( sublist, '\n', '<br>' )
-- Set categories for errors
if linklessCat and not hasLinks then
sublist = sublist .. string.format( '[[Category:%s]]', linklessCat )
addWarning( title, noLinks )
end
if hasErrors then
sublist = sublist .. string.format( '[[Category:%s]]', errorCat )
addWarning( title )
end
return '<div class="ts-NL">' .. intro .. sublist .. '</div>'
end
return p