ФЭНДОМ


local core = require( 'Модуль:Навбокс/Ядро' )
local library = require( 'Модуль:Библиотека' )
 
function classesHandle( classString )
    if not classString then
        return
    end
    return library.string.split( classString, '%s', true )
end
 
function stylesHandle( stylesString )
    if not stylesString then
        return
    end
    local rawStyles = library.string.split( stylesString, ';' )
    local styles = {}
    for i, style in ipairs( rawStyles ) do
        local handledStyle = library.string.split( style, ':' )
        styles[ handledStyle[1] ] = handledStyle[2]
    end
    return styles
end
 
 
local modulePattern = {}
 
function modulePattern:_initialise( level )
    for i, permittedLevel in ipairs( self._permittedLevels ) do
        if permittedLevel == level then
            return
        end
    end
    error( self._name..'Module: уровень "'..level..'" не разрешен' )
end
 
function modulePattern:_run()
    for i, indispensableLevel in ipairs( self._indispensableLevels ) do
        if not self._settings[ indispensableLevel ] then
            error( self._name..'Module: уровень "'..indispensableLevel..'" не инициализирован' )
        end
    end
end
 
function modulePattern:_check( level )
    if not self._settings[ level ] then
        error( self._name..'Module: уровень "'..level..'" не инициализирован' )
    end
end
 
function modulePattern:_defSetting( setting, space )
    local newSetting
    if not space then
        space = self._name
    end
    local levels = { 'main', 'section', 'partition', 'content' }
    for i, level in ipairs( levels ) do
        if self._allSettings[ space ] and self._allSettings[ space ][ level ] and
        self._allSettings[ space ][ level ][ setting ] then
            newSetting = self._allSettings[ space ][ level ][ setting ]
        end
    end
    return newSetting
end
 
function modulePattern:_baseCheck( name, misc, allows )
    local arg = misc.settings[ name ]
    local forbidNil = misc.forbidNil
    local moduleName = misc.moduleName
    --на наличие
    if not arg then
        if not forbidNil then
            return
        else
            error( moduleName..': "'..name..'" должен быть определён' )
        end
    end
    --на значение
    if allows then
        for i, val in ipairs( allows ) do
            if val == arg then
                return
            end
        end
        error( moduleName..': "'..name..'" должен быть'..library.string.join( allows, 'or' ) )
    end
end
 
function modulePattern:tune( level, settings )
    if not self._settings[ level ] then
        error( self._name..'Module: уровень "'..level..'" не инициализирован' )
    end
    self:_check( level, settings )
    self._settings[ level ] = self._library.table.mergeTables( self._settings[level], settings )
end
 
modulePattern.__index = modulePattern
 
--сворачивание
collapsible = {}
 
collapsible.settings = {}
collapsible.settings.base = {
    collapsible = 'false',
    collapsed = 'false',
    openCurrent = 'close',
    controlElement = 'header',
    expandText = '',
    collapseText = '',
    expandTooltip = '',
    collapseTooltip = ''
}
collapsible.settings.standart = {
    collapsible = 'true',
    collapsed = 'true',
    openCurrent = 'close',
    controlElement = 'header',
    expandText = 'Показать',
    collapseText = 'Скрыть',
    expandTooltip = 'Нажмите чтобы развернуть секцию',
    collapseTooltip = 'Нажмите чтобы свернуть секцию'
}
 
function collapsible.prepare( settings, parent )
    parent.settings.collapsible = {}
    local obj = {}
    obj._allSettings = parent.settings
    obj._settings = parent.settings.collapsible
    obj._library = library
    obj._modules = parent
    obj._permittedLevels = { 'main', 'section' }
    obj._indispensableLevels = { 'main' }
    obj._name = 'collapsible'
    setmetatable( obj, collapsible )
    collapsible.__index = collapsible
    obj:initialise( 'main', settings )
    return obj
end
 
function collapsible:initialise( level, settings )
    self:_initialise( level )
    if not settings then
        if level == 'main' then
            settings = 'base'
        else
            settings = {}
        end
    end
    if type( settings ) == 'string' then
        if self.settings[ settings ] then
            self._settings[ level ] = mw.clone( self.settings[settings] )
        else
            error( 'collapsibleModule: настройки с именем "'..settings..'" не существует' )
        end
    elseif type( settings ) == 'table' then
        if level == 'main' then
            self:_check( level, settings, true )
        else
            self:_check( level, settings )
        end
        self._settings[ level ] = settings
    else
         error( 'collapsibleModule: "settings" должна быть строкой либо таблицей' )
    end
end
 
function collapsible:run( attrs )
    self:_run()
    local settings
    if self._settings[ 'section' ] then
        settings = self._settings[ 'section' ]
    else
        settings = self._settings[ 'main' ]
    end
    if settings.collapsible == 'false' then
        return attrs
    end
    --запись настроек
    local newAttrs = {}
    local writeSetting = function( setName, attrName )
        if not attrName then
            attrName = setName
        end
        newAttrs[ 'data-'..attrName ] = settings[ setName ]
    end
    writeSetting( 'collapsible' )
    writeSetting( 'collapsed' )
    writeSetting( 'openCurrent', 'open-current' )
    writeSetting( 'controlElement', 'control-elem' )
    writeSetting( 'expandText', 'expand-text' )
    writeSetting( 'collapseText', 'collapse-text' )
    writeSetting( 'expandTooltip', 'expand-tooltip' )
    writeSetting( 'collapseTooltip', 'collapse-tooltip' )
    if attrs then
        newAttrs = self._library.table.mergeTables( attrs, newAttrs )
    end
    return newAttrs
end
 
function collapsible:_check( level, settings, prepare )
    local misc = { 
        settings = settings, 
        moduleName = 'menuModule',
        forbidNil = prepare
    }
    self:_baseCheck( 'collapsible', misc, { 'true', 'false' } )
    self:_baseCheck( 'collapsed', misc, { 'true', 'false' } )
    self:_baseCheck( 'openCurrent', misc, {'open', 'close'} )
    self:_baseCheck( 'controlElement', misc, {'header', 'button'} )
    self:_baseCheck( 'expandText', misc )
    self:_baseCheck( 'collapseText', misc )
    self:_baseCheck( 'expandTooltip', misc )
    self:_baseCheck( 'collapseTooltip', misc )
end
 
setmetatable( collapsible, modulePattern )
 
--меню
menu = {}
 
menu.settings = {}
menu.settings.base = {
    status = 'false',
    text = '',
    separator = ''
}
menu.settings.standart = {
    status = 'firstRoot',
    text = 'standart',
    separator = '·'
}
 
function menu.prepare( settings, parent )
    parent.settings.menu = {}
    local obj = {}
    obj._allSettings = parent.settings
    obj._settings = parent.settings.menu
    obj._library = library
    obj._modules = parent
    obj._permittedLevels = { 'main', 'section' }
    obj._indispensableLevels = { 'main', 'section' }
    obj._name = 'menu'
    obj._standartMenus = {}
    local nsName = mw.getCurrentFrame():getParent():getTitle()
    local name = library.string.split(nsName, ':', false, function( str, pos )
        if pos[ 4 ] == 0 then
            return true
        end
    end)[ 2 ]
    obj._standartMenus.standart = {
        [ 1 ] = '<span title="Просмотр шаблона">[['..nsName..'|П]]</span>',
        [ 2 ] = '<span title="Обсуждение шаблона">[[Template talk:'..name..'|О]]</span>',
        [ 3 ] = '<span class="plainlinks" title="Редактирование шаблона">['..mw.site.server..'/wiki/'..nsName..'?action=edit Р]</span>',
        separator = '·'
    }
    setmetatable( obj, menu )
    menu.__index = menu
    obj:initialise( 'main', settings )
    return obj
end
 
function menu:initialise( level, settings )
    self:_initialise( level )
    if not settings then
        if level == 'main' then
            settings = 'base'
        else
            settings = {}
        end
    end
    if type( settings ) == 'string' then
        if self.settings[ settings ] then
            self._settings[ level ] = mw.clone( self.settings[settings] )
        else
            error( 'menuModule: настройки с именем "'..settings..'" не существует' )
        end
    elseif type( settings ) == 'table' then
        if level == 'main' then
            self:_check( level, settings, true )
        else
            self:_check( level, settings )
        end
        self._settings[ level ] = settings
    else
         error( 'menuModule: "settings" должна быть строкой либо таблицей' )
    end
end
 
function menu:run( sectionData )
    self:_run()
    local menuStatus = self:_defSetting( 'status' )
    if menuStatus == 'false' or ( menuStatus == 'allRoot' and not sectionData.root )
    or ( menuStatus == 'firstRoot' and  (not sectionData.root or sectionData.number ~= 1) ) then
        return sectionData.headerText
    end
    local content = self:_defSetting( 'text' )
    if not content then
        return sectionData.headerText
    end
    local wrapper = mw.html.create( 'div' )
    wrapper:addClass( 'navbox_menu' )
    local collapsible = self:_defSetting( 'collapsible', 'collapsible' )
    local controlElement = self:_defSetting( 'controlElement', 'collapsible' ) 
    if collapsible == 'true' and controlElement == 'header' then
        wrapper:addClass( 'navbox_noClickableArea' )
    end
    if type( content ) == 'string' and not self._standartMenus[ content ] then
        wrapper:wikitext( content )
        return sectionData.headerText..tostring( wrapper )
    end
    local menuTable
    if type( content ) == 'table' then
        menuTable = content
    else
        menuTable = self._standartMenus[ content ]
    end
    local separator = self:_defSetting( 'separator' )
    if not separator then
        separator = menuTable.separator
    end
    wrapper:wikitext( self._library.string.join( menuTable, separator ) )
    return sectionData.headerText..tostring( wrapper )
end
 
function menu:_check( level, settings, prepare )
    local misc = { 
        settings = settings, 
        moduleName = 'menuModule',
        forbidNil = prepare
    }
    if level == 'main'  then
        self:_baseCheck( 'status', misc, { 'true', 'false', 'firstRoot', 'allRoot' } )
    else
        self:_baseCheck( 'status', misc, { 'true', 'false' } )
    end
    self:_baseCheck( 'text', misc )
    self:_baseCheck( 'separator', misc )
end
 
setmetatable( menu, modulePattern )
 
--парсер
local parser = {}
 
parser.settings = {}
parser.settings.base = {
    parser = 'none',
    separator = 'common'
}
parser.settings.standart = {
    parser = 'standart',
    separator = 'common'
}
 
function parser.prepare( settings, parent )
    parent.settings.parser = {}
    local obj = {}
    obj._allSettings = parent.settings
    obj._settings = parent.settings.parser
    obj._library = library
    obj._modules = parent
    obj._usedParsers = {}
    obj._permittedLevels = { 'main', 'section', 'partition', 'content' }
    obj._indispensableLevels = { 'main' }
    obj._name = 'parser'
    setmetatable( obj, parser )
    parser.__index = parser
    obj:initialise(  'main', settings )
    return obj
end
 
function parser:initialise( level, settings )
    self:_initialise( level )
    if not settings then
        if level == 'main' then
            settings = 'base'
        else
            settings = {}
        end
    end
    if type( settings ) == 'string' then
        if self.settings[ settings ] then
            self._settings[ level ] = mw.clone( self.settings[settings] )
        else
            error( 'parserModule: настройки с именем "'..settings..'" не существует' )
        end
    elseif type( settings ) == 'table' then
        if level == 'main' then
            self:_check( level, settings, true )
        else
            self:_check( level, settings )
        end
        self._settings[ level ] = settings
    else
         error( 'parserModule: "settings" должна быть строкой либо таблицей' )
    end
end
 
function parser:run( text )
    self:_run()
    local parserSettings = self:_defSetting( 'parser' )
    local separator = self:_defSetting( 'separator' )
    if parserSettings == 'none' then
        return text
    end
    local parser
    if type( parserSettings ) == 'string' then
        if self._usedParsers[ parserSettings ] and self._usedParsers[ parserSettings ][ separator ] then
            parser = self._usedParsers[ parserSettings ][ separator ]
        else
            local settings
            if separator == 'common' then
                settings = parserSettings
            else
                settings = {
                    baseSettingName = parserSettings,
                    actions = { separators = 'set' },
                }
                local baseSetting = self._library.parser.getSetting( parserSettings )
                if baseSetting.separators and baseSetting.separators[ 1 ] then
                    settings.separators = {
                        [ 1 ] = { baseSetting.separators[ 1 ][ 1 ], separator }
                    }
                end
            end
            parser = self._library.parser.create( settings )
            if not self._usedParsers[ parserSettings ] then
                self._usedParsers[ parserSettings ] = {}
            end
            self._usedParsers[ parserSettings ][ separator ] = parser
        end
    else
        parser = self._library.parser.create( parserSettings )
    end
    return parser:parse( text )
end
 
function parser:_check( level, settings, prepare )
    local misc = { 
        settings = settings, 
        moduleName = 'parserModule',
        forbidNil = prepare
    }
    self:_baseCheck( 'parser', misc )
    if settings['parser'] and type( settings['parser'] ) == 'string' and settings['parser'] ~= 'none' and
    not self._library.parser.checkSetting( settings['parser'] ) then
        error( 'parserModule: парсера с таким названием не существует' )
    end
    self:_baseCheck( 'separator', misc )
end
 
setmetatable( parser, modulePattern )
 
local modules = {}
 
modules.create = function()
    local obj = {}
    obj.settings = {}
    obj._usedModules = {}
    local self = modules
    setmetatable( obj, self )
    self.__index = self
    return obj
end
 
function modules:prepare( name, settings )
    if not modules.allModules[ name ] then
        error( 'Неверное имя модуля' )
    end
    self._usedModules[ name ] = modules.allModules[ name ].prepare( settings, self )
end
 
function modules:initialise( name, level, settings )
    if not self._usedModules[ name ] then
        error( 'Неверное имя модуля' )
    end
    if not self._usedModules[ name ] then
        error( 'Данный модуль не используется' )
    end
    self._usedModules[ name ]:initialise( level, settings )
end
 
function modules:tune( name, level, settings )
    if not self._usedModules[ name ] then
        error( 'Неверное имя модуля' )
    end
    if not self._usedModules[ name ] then
        error( 'Данный модуль не используется' )
    end
    self._usedModules[ name ]:tune( level, settings )
end
 
function modules:run( name, elem, data )
    if not self._usedModules[ name ] then
        error( 'Неверное имя модуля' )
    end
    if not self._usedModules[ name ] then
        error( 'Данный модуль не используется' )
    end
    return self._usedModules[ name ]:run( elem, data )
end
 
modules.allModules = {}
modules.allModules.collapsible = collapsible
modules.allModules.menu = menu
modules.allModules.parser = parser
 
function createTableContent( cells, navbox, name, parentName )
    local content = ''
    for i, val in ipairs( cells ) do
        local wrapper = mw.html.create( 'div' )
        if val.moreCaption then
            wrapper:wikitext( '[[Файл:'..val.image..'|link='..val.captionLink..']][[Файл:'..val.moreImage..'|link='..val.moreCaptionLink..']]<br />[['..val.captionLink..'|'..val.caption..']] [['..val.moreCaptionLink..'|'..val.moreCaption..']]' )
        else
            wrapper:wikitext( '[[Файл:'..val.image..'|link='..val.captionLink..']]<br />[['..val.captionLink..'|'..val.caption..']]' )
        end
        content = content..tostring( wrapper )
    end
    navbox:createContent( content, name, parentName, { classes = {'navbox_table'} } )
end
 
function universalCreate( args )
    --подготовка настроек
    local prepareCoreSettings = function( prefix )
        if not prefix then
            prefix = ''
        end
        local settings = {}
        settings.classes = classesHandle( args[ prefix..'классы' ] )
        settings.styles = stylesHandle( args[ prefix..'стили' ] )
        settings.attrs = {}
        return settings
    end
    local prepareCollapsibleSettings = function( prefix )
        if not prefix then
            prefix = ''
        end
        local settings = {}
        local lAT = library.arguments.checkAndTranslate
        settings.collapsible = lAT( prefix..'сворачивается', {['да']='true', ['нет']='false'} )
        settings.collapsed = lAT( prefix..'свёрнут', {['да']='true', ['нет']='false'} )
        settings.openCurrent = lAT( prefix..'активные секции', {['открыты'] = 'open', ['закрыты'] = 'close'} )
        settings.controlElement = lAT( prefix..'управляющий элемент', {['заголовок']='header', ['кнопка']='button'} )
        settings.expandText = library.arguments.checkAndReturn( prefix..'текст развернуть' )
        settings.collapseText = library.arguments.checkAndReturn( prefix..'текст свернуть' )
        settings.expandTooltip = library.arguments.checkAndReturn( prefix..'подсказка развернуть' )
        settings.collapseTooltip = library.arguments.checkAndReturn( prefix..'подсказка свернуть' )
        return settings
    end
    local prepareMenuSettings = function( prefix )
        local settings = {}
        if not prefix then
            prefix = ''
            settings.status = library.arguments.checkAndTranslate( 'меню', {['для всех']='true', ['нет']='false', ['для всех корневых']='allRoot', ['для первого корневого']='firstRoot'} )
        else
            settings.status = library.arguments.checkAndTranslate( prefix..'меню', {['да']='true', ['нет']='false'} )
        end
        settings.text = library.arguments.checkAndReturn( prefix..'текст меню' )
        settings.separator = library.arguments.checkAndReturn( prefix..'сепаратор меню' )
        return settings
    end
    local prepareParserSettings = function( prefix )
        local settings = {}
        if not prefix then
            prefix = ''
        end
        settings.parser = library.arguments.translate( prefix..'парсер', {['нет']='none'}, args[prefix..'парсер'] )
        settings.separator = library.arguments.translate( prefix..'сепаратор парсера', {['стандарт']='common'}, args[prefix..'сепаратор парсера'] )
        return settings
    end
    local coreMainSettings = {}
    coreMainSettings.attributes = prepareCoreSettings()
    --подключение модулей
    modulesCore = modules.create()
    --сворачивание
    modulesCore:prepare( 'collapsible', 'standart' )
    local collapsibleMainSettings = prepareCollapsibleSettings()
    modulesCore:tune( 'collapsible', 'main', collapsibleMainSettings )
    --меню
    modulesCore:prepare( 'menu', 'standart' )
    local menuMainSettings = prepareMenuSettings()
    modulesCore:tune( 'menu', 'main', menuMainSettings )
    --парсер
    modulesCore:prepare( 'parser', 'standart' )
    local parserMainSettings = prepareParserSettings()
    modulesCore:tune( 'parser', 'main', parserMainSettings )
    --активация модулей
    coreMainSettings.attributes.attrs = modulesCore:run( 'collapsible', coreMainSettings.attributes.attrs )
    --создание базового навбокса
    local navbox = core.create( coreMainSettings )
    function createBlock( prefix )
        local index = 1
        local argName
        if prefix then
            argName = prefix..'.'..index
        else
            argName = 'блок '..index
        end
        local arg = args[ argName ]
        while arg do
            local argType = library.arguments.checkAndReturn( argName..' тип', {'секция', 'раздел', 'содержимое'}, true )
            if argType == 'секция' then
                local coreSectionSettings = prepareCoreSettings( argName..' ' )
                --сворачивание
                local collapsibleSectionSettings = prepareCollapsibleSettings( argName..' ' )
                modulesCore:initialise( 'collapsible', 'section', collapsibleSectionSettings )
                --меню
                local menuSectionSettings = prepareMenuSettings( argName..' ' )
                modulesCore:initialise( 'menu', 'section', menuSectionSettings )
                --парсер
                local parserSectionSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'section', parserSectionSettings )
                --активация модулей
                coreSectionSettings.attrs = modulesCore:run( 'collapsible', coreSectionSettings.attrs )
                local menuData = { headerText = arg, root = not prefix, number = index }
                arg = modulesCore:run( 'menu', menuData )
                --создание секции
                navbox:createSection( arg, argName, prefix, coreSectionSettings )
            elseif argType == 'раздел' then
                local corePartitionSettings = prepareCoreSettings( argName..' ' )
                local parserPartitionSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'partition', parserPartitionSettings )
                navbox:createPartition( arg, argName, prefix, corePartitionSettings )
            elseif argType == 'содержимое' then
                local coreContentSettings = prepareCoreSettings( argName..' ' )
                --парсер
                local parserContentSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'content', parserContentSettings )
                --активация модулей
                arg = modulesCore:run( 'parser', arg )
                --создание
                navbox:createContent( arg, argName, prefix, coreContentSettings )
            end
            if args[ argName..'.'..1 ] then
                createBlock( argName )
            end
            index = index + 1
            if prefix then
                argName = prefix..'.'..index
            else
                argName = 'блок '..index
            end
            arg = args[ argName ]
        end
    end
    createBlock()
    return navbox:assembly()
end
 
function charactersCreate( args, pattern )
    modulesCore = modules.create()
    modulesCore:prepare( 'collapsible', 'standart' )
    modulesCore:prepare('parser', {
        parser =  {
            baseSettingName = 'standart',
            actions = {
                textHandler = 'replace'
            },
            textHandler = function( text )
                local featuredText = mw.ustring.gsub( text, '^%s*', '' )
                featuredText = mw.ustring.gsub( featuredText, '%s*$', '' )
                if mw.ustring.find( featuredText, '|' ) then
                    return '[['..featuredText..']]'
                else
                    return '[['..pattern[ 1 ]..featuredText..pattern[ 2 ]..'|'..featuredText..']]'
                end
            end
        },
        separator = 'common'
    })
    local globalSettings = {}
    globalSettings.attributes = {}
    globalSettings.attributes.attrs = modulesCore:run( 'collapsible' )
    local navbox = core.create( globalSettings )
    local addMainCharacter = function( arr, name, moreName )
        local image = args[ name..' изображение' ]
        if not image then
            image = name..' навбокс.png'
        end
        local link = pattern[ 1 ]..name..pattern[ 2 ]
        local moreImage
        local moreLink
        if moreName then
            moreImage = args[ moreName..' изображение' ]
            if not moreImage then
                moreImage = moreName..' навбокс.png'
            end
            moreLink = pattern[ 1 ]..moreName..pattern[ 2 ]
        end
        table.insert(arr, {caption=name, captionLink=link, image=image, moreCaption=moreName, moreCaptionLink=moreLink, moreImage=moreImage})
    end
    local checkPartition = function( argName )
        if not args[ argName ] then
            error( 'Отсутствует раздел "'..argName..'"' )
        end
    end
    navbox:createSection( 'Главные персонажи', 'ГП' )
    local mChars = {}
    addMainCharacter( mChars, 'Сумеречная Искорка', 'Спайк' )
    addMainCharacter( mChars, 'Эпплджек' )
    addMainCharacter( mChars, 'Флаттершай' )
    addMainCharacter( mChars, 'Пинки Пай' )
    addMainCharacter( mChars, 'Радуга Дэш' )
    addMainCharacter( mChars, 'Рарити' )
    createTableContent( mChars, navbox,  'ГПС', 'ГП' )
    navbox:createSection( 'Второстепенные персонажи', 'ВП' )
    local sCC = 1
    local group = args[ 'второстепенные персонажи раздел '..sCC ]
    while group do
        local name = args[ 'второстепенные персонажи раздел '..sCC..' название' ]
        if not name then
            error( 'У раздела второстепенных персонажей №"'..sCC..'" не указано название' )
        end
        navbox:createPartition( name, 'ВП'..sCC, 'ВП' )
        local text = modulesCore:run( 'parser', group )
        navbox:createContent( text, 'ВП'..sCC..'С', 'ВП'..sCC )
        sCC = sCC + 1
        group = args[ 'второстепенные персонажи раздел '..sCC ]
    end
    navbox:createSection( 'Фоновые персонажи', 'ФП' )
    checkPartition( 'фоновые земные пони' )
    navbox:createPartition( '[[Земные пони]][[Файл:Earthpony_picto.png|20px|link=Земные пони]]', 'ФПЗ', 'ФП' )
    local eText = modulesCore:run( 'parser', args[ 'фоновые земные пони' ] )
    navbox:createContent( eText, 'ФПЗС', 'ФПЗ' )
    checkPartition( 'фоновые пегасы' )
    navbox:createPartition( '[[Пегасы]][[Файл:Pegasus_picto.png|20px|link=Пегасы]]', 'ФПП', 'ФП' )
    local pText = modulesCore:run( 'parser', args[ 'фоновые пегасы' ] )
    navbox:createContent( pText, 'ФППС', 'ФПП' )
    checkPartition( 'фоновые единороги' )
    navbox:createPartition( '[[Единороги]][[Файл:Unicorn_picto.png|20px|link=Единороги]]', 'ФПЕ', 'ФП' )
    local uText = modulesCore:run( 'parser', args[ 'фоновые единороги' ] )
    navbox:createContent( uText, 'ФПЕС', 'ФПЕ' )
    return navbox:assembly()
end
 
function episodesCreate( name, handler, films, parser )
    if not films then
        error( 'Отсутствует раздел "фильмы"' )
    end
    local seriesApi = require( 'Модуль:Серии' )
    local seasonsAmount = seriesApi:getLength()
    modulesCore = modules.create()
    modulesCore:prepare( 'collapsible', 'standart' )
    modulesCore:prepare( 'parser', 'standart' )
    modulesCore:tune( 'parser', 'main', {parser = parser} )
    local globalSettings = {}
    globalSettings.attributes = {}
    globalSettings.attributes.attrs = modulesCore:run( 'collapsible' )
    local navbox = core.create( globalSettings )
    navbox:createSection( name, 'О' )
    for i = 1, seasonsAmount do
        local content = ''
        navbox:createSection( 'Сезон '..i, 'С'..i, 'О' )
        seriesApi:forEach(function( episode, i )
            content = content..handler( episode, i )
        end, i)
        navbox:createContent( content, 'С'..i..'э', 'С'..i )
    end
    navbox:createSection( 'Фильмы и короткометражки', 'Ф', 'О' )
    local filmsContent = modulesCore:run( 'parser', films )
    navbox:createContent( filmsContent, 'Фэ', 'Ф' )
    return navbox:assembly()
end
 
function kindsCreate( args )
    modulesCore = modules.create()
    modulesCore:prepare( 'collapsible', 'standart' )
    modulesCore:tune( 'collapsible', 'main', { collapsed = 'false' } )
    local globalSettings = {}
    globalSettings.attributes = {}
    globalSettings.attributes.attrs = modulesCore:run( 'collapsible' )
    local navbox = core.create( globalSettings )
    local addKind = function( arr, kind )
        local image = args[ kind ]
        if not image then
            image = kind..' навбокс.png'
        end
        table.insert( arr, {caption=kind, captionLink=kind, image=image} )
    end
    navbox:createSection( 'Виды пони', 'ВП', nil, {collapsed=false} )
    local kinds = {}
    addKind( kinds, 'Земные пони' )
    addKind( kinds, 'Пегасы' )
    addKind( kinds, 'Единороги' )
    addKind( kinds, 'Аликорны' )
    addKind( kinds, 'Кристальные пони' )
    createTableContent( kinds, navbox,  'ВПС', 'ВП' )
    return navbox:assembly()
end
 
function standartCreate( args )
    --подготовка настроек
    local prepareCoreSettings = function( prefix )
        if not prefix then
            prefix = ''
        end
        local settings = {}
        settings.classes = classesHandle( args[ prefix..'классы' ] )
        settings.styles = stylesHandle( args[ prefix..'стили' ] )
        settings.attrs = {}
        return settings
    end
    local prepareCollapsibleSettings = function( prefix )
        if not prefix then
            prefix = ''
        end
        local settings = {}
        local lAT = library.arguments.checkAndTranslate
        settings.collapsible = lAT( prefix..'сворачивается', {['да']='true', ['нет']='false'} )
        settings.collapsed = lAT( prefix..'свёрнут', {['да']='true', ['нет']='false'} )
        settings.openCurrent = lAT( prefix..'активные секции', {['открыты'] = 'open', ['закрыты'] = 'close'} )
        settings.controlElement = lAT( prefix..'управляющий элемент', {['заголовок']='header', ['кнопка']='button'} )
        return settings
    end
    local prepareParserSettings = function( prefix )
        local settings = {}
        if not prefix then
            prefix = ''
        end
        settings.parser = library.arguments.translate( prefix..'парсер', {['нет']='none'}, args[prefix..'парсер'] )
        settings.separator = library.arguments.translate( prefix..'сепаратор парсера', {['стандарт']='common'}, args[prefix..'сепаратор парсера'] )
        return settings
    end
    local coreMainSettings = {}
    coreMainSettings.attributes = prepareCoreSettings()
    --подключение модулей
    modulesCore = modules.create()
    --сворачивание
    modulesCore:prepare( 'collapsible', 'standart' )
    local collapsibleMainSettings = prepareCollapsibleSettings()
    modulesCore:tune( 'collapsible', 'main', collapsibleMainSettings )
    --парсер
    modulesCore:prepare( 'parser', 'standart' )
    local parserMainSettings = prepareParserSettings()
    modulesCore:tune( 'parser', 'main', parserMainSettings )
    --активация модулей
    coreMainSettings.attributes.attrs = modulesCore:run( 'collapsible', coreMainSettings.attributes.attrs )
    --создание базового навбокса
    local navbox = core.create( coreMainSettings )
    function createBlock( prefix, nesting )
        local index = 1
        local argName
        if prefix then
            argName = prefix..'.'..index
        else
            argName = 'блок '..index
        end
        if not nesting then
            nesting = {
                section = 0,
                partition = 0
            }
        end
        local arg = args[ argName ]
        while arg do
            local argType = library.arguments.checkAndReturn( argName..' тип', {'секция', 'раздел', 'содержимое'}, true )
            local newNesting = mw.clone( nesting )
            if argType == 'секция' then
                if newNesting.section == 2 then
                    error( 'предельная вложенность по секциям' )
                end
                newNesting.section = newNesting.section + 1
                local coreSectionSettings = prepareCoreSettings( argName..' ' )
                --сворачивание
                local collapsibleSectionSettings = prepareCollapsibleSettings( argName..' ' )
                modulesCore:initialise( 'collapsible', 'section', collapsibleSectionSettings )
                --парсер
                local parserSectionSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'section', parserSectionSettings )
                --активация модулей
                coreSectionSettings.attrs = modulesCore:run( 'collapsible', coreSectionSettings.attrs )
                --создание секции
                navbox:createSection( arg, argName, prefix, coreSectionSettings )
            elseif argType == 'раздел' then
                if newNesting.partition == 2 then
                    error( 'предельная вложенность по разделам' )
                end
                newNesting.partition = newNesting.partition + 1
                local corePartitionSettings = prepareCoreSettings( argName..' ' )
                local parserPartitionSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'partition', parserPartitionSettings )
                navbox:createPartition( arg, argName, prefix, corePartitionSettings )
            elseif argType == 'содержимое' then
                local coreContentSettings = prepareCoreSettings( argName..' ' )
                --парсер
                local parserContentSettings = prepareParserSettings( argName..' ' )
                modulesCore:initialise( 'parser', 'content', parserContentSettings )
                --активация модулей
                arg = modulesCore:run( 'parser', arg )
                --создание
                navbox:createContent( arg, argName, prefix, coreContentSettings )
            end
            if args[ argName..'.'..1 ] then
                createBlock( argName, newNesting )
            end
            index = index + 1
            if prefix then
                argName = prefix..'.'..index
            else
                argName = 'блок '..index
            end
            arg = args[ argName ]
        end
    end
    createBlock()
    return navbox:assembly()
end
 
local navbox = {}
 
function navbox.universal( frame )
    local withoutErrors, result = pcall( universalCreate, frame.args )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.characters( frame )
    local withoutErrors, result = pcall( charactersCreate, frame.args, {'', ''} )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.galleriesCharacters( frame )
    local withoutErrors, result = pcall( charactersCreate, frame.args, {'', '/Галерея'} )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.galleries( frame )
    local parserSettings = {
        baseSettingName = 'standart',
        actions = { textHandler = 'replace' },
        textHandler = function( text )
            local featuredText = mw.ustring.gsub( text, '^%s*', '' )
            featuredText = mw.ustring.gsub( featuredText, '%s*$', '' )
            locallinkAndName = library.string.split( featuredText, '|' )
            if not locallinkAndName[ 2 ] then
                return '[['..featuredText..'/Галерея|'..featuredText..']]'
            else
                return '[['..locallinkAndName[1]..'/Галерея|'..locallinkAndName[2]..']]'
            end
        end
    }
    local handler = function( episode, i )
        if i == 1 then
            return '[['..episode.pageName..'/Галерея|'..episode.name..']]'
        else
            return ' • [['..episode.pageName..'/Галерея|'..episode.name..']]'
        end
    end
    local withoutErrors, result = pcall( episodesCreate, 'Галереи', handler, frame.args[ 'фильмы' ], parserSettings )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.transcripts( frame )
    local parserSettings = {
        baseSettingName = 'standart',
        actions = { textHandler = 'replace' },
        textHandler = function( text )
            local featuredText = mw.ustring.gsub( text, '^%s*', '' )
            featuredText = mw.ustring.gsub( featuredText, '%s*$', '' )
            locallinkAndName = library.string.split( featuredText, '|' )
            if not locallinkAndName[ 2 ] then
                return '[[Стенограммы/'..featuredText..'|'..featuredText..']]'
            else
                return '[[Стенограммы/'..locallinkAndName[1]..'|'..locallinkAndName[2]..']]'
            end
        end
    }
    local handler = function( episode, i, parser )
        if i == 1 then
            return '[[Стенограммы/'..episode.pageName..'|'..episode.name..']]'
        else
            return ' • [[Стенограммы/'..episode.pageName..'|'..episode.name..']]'
        end
    end
    local withoutErrors, result = pcall( episodesCreate, 'Стенограммы', handler, frame.args[ 'фильмы' ], parserSettings )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.kinds( frame )
    local withoutErrors, result = pcall( kindsCreate, frame.args )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
function navbox.standart( frame )
    local withoutErrors, result = pcall( standartCreate, frame.args )
    if not withoutErrors then
        return library.errorPrint( result )
    else
        return result
    end
end
 
return navbox
Материалы сообщества доступны в соответствии с условиями лицензии CC-BY-SA , если не указано иное.