Для документации этого модуля может быть создана страница Модуль:Навбокс/Ядро/doc
local standartElements = {
section = {
children = true,
level = 1,
create = function( text, children )
local section = mw.html.create( 'div' )
section:addClass( 'navbox_section' )
local header = mw.html.create( 'div' )
header:addClass( 'navbox_sectionHeader' )
header:wikitext( text )
section:node( header )
local body = mw.html.create( 'div' )
body:addClass( 'navbox_sectionBody' )
for i, child in ipairs( children ) do
body:node( child )
end
section:node( body )
return section
end
},
partition = {
children = true,
level = 2,
create = function( text, children )
local partition = mw.html.create( 'div' )
partition:addClass( 'navbox_partition' )
local header = mw.html.create( 'div' )
header:addClass( 'navbox_partitionHeader' )
header:wikitext( text )
partition:node( header )
local body = mw.html.create( 'div' )
body:addClass( 'navbox_partitionBody' )
for i, child in ipairs( children ) do
body:node( child )
end
partition:node( body )
return partition
end
},
content = {
children = false,
create = function( text )
local body = mw.html.create( 'div' )
body:addClass( 'navbox_content' )
body:wikitext( text )
return body
end
}
}
--
local navbox = {}
--[[settings(?) = table -- Настройки навбокса.
{
attributes(?) = table -- Аттрибуты навбокса
{
classes(?) = string, -- Классы обертки навбокса;
styles(?) = string, -- стили обертки навбокса;
attrs(?) = string -- HTML атрибуты обертки навбокса.
}
}
]]--
function navbox.create( settings )
local self = navbox
local obj = {}
--
if settings and settings.attributes then
self._attributes = mw.clone( settings.attributes )
end
--
obj._elementsRoot = {}
obj._elements = {}
obj._navbox = nil
obj._modulesData = {}
--
obj._library = require( 'Модуль:Библиотека' )
obj._elementsLibrary = mw.clone( standartElements )
obj._modulesLibrary = require( 'Модуль:Навбокс/Модули' )
--
setmetatable( obj, self )
self.__index = self
return obj
end
--[[
params = table
{
type = string -- Тип элемента;
text = string -- текстовое содержимое элемента;
id = string -- идентификатор элемента;
parentId = string -- идентификатор элемента, который должен быть родительским добавляемому;
attributes(?) = table -- Аттрибуты элемента;
{
classes(?) = string, -- Классы обертки навбокса;
styles(?) = string, -- стили обертки навбокса;
attrs(?) = string -- HTML атрибуты обертки навбокса.
},
modules(?) = table -- таблица модулей элемента.
}
]]--
function navbox:addElement( params )
if self._navbox then
error( 'Навбокс закрыт для расширения' )
end
self:_checkElement( params.type, params.id, params.parentId )
if params.modules then
self:_checkModules( params.modules, params.type, params.id )
end
local billet = self:_createBillet( params )
self:_collectBillet( billet, params.parentId )
end
--[[
params = table
{
type = string -- Тип элемента;
text = string -- текстовое содержимое элемента;
id = string -- идентификатор элемента;
parentId = string -- идентификатор элемента, который должен быть родительским добавляемому;
attributes(?) = table -- Аттрибуты элемента;
{
classes(?) = string, -- Классы обертки навбокса;
styles(?) = string, -- стили обертки навбокса;
attrs(?) = string -- HTML атрибуты обертки навбокса.
},
modules(?) = table -- таблица модулей элемента.
}
]]--
function navbox:_createBillet( params )
local elementType = params.type
local rawModules = params.modules
local requiredModules = self._elementsLibrary[ elementType ].requiredModules
local billet = {
text = params.text,
type = elementType,
id = params.id
}
if params.attributes then
billet.attributes = params.attributes
end
if rawModules or requiredModules then
local modules = {}
if rawModules then
for name, setting in pairs( rawModules ) do
local moduleSettings = mw.clone( setting )
local dependences = self._modulesLibrary[ name ].dependences
moduleSettings._name = name
if dependences then
moduleSettings._dependences = {}
for i, dependence in ipairs( dependences ) do
if rawModules[ dependence ] then
dependencesData[ dependence ] = mw.clone( rawModules[dependence] )
end
end
end
table.insert( modules, moduleSettings )
end
end
if requiredModules then
for name, setting in pairs( requiredModules ) do
if not rawModules[ name ] then
local moduleSettings = mw.clone( requiredModules[name] )
moduleSettings._name = name
table.insert( modules, moduleSettings )
end
end
end
table.sort( modules, function( mod1, mod2)
local prior1 = self._modulesLibrary[ mod1._name ].priority
local prior2 = self._modulesLibrary[ mod2._name ].priority
return prior1 < prior2
end )
billet.modules = modules
end
return billet
end
--[[
elementType = string -- Тип элемента.
id = string -- Идентификатор элемента.
parentId = string -- Идентификатор элемента, который должен быть родительским добавляемому.
]]--
function navbox:_checkElement( elementType, id, parentId )
local elementPattern = self._elementsLibrary[ elementType ]
-- На верный тип элемента
if not elementPattern then
error( 'Несуществующий тип элементов' )
end
-- На корректный айди
if self._elements[ id ] then
error( 'Элемент "'..id..'", уже определён' )
end
-- На наличие в библиотеке требуемых модулей
if elementPattern.requiredModules then
for name, requiredModule in pairs( elementPattern.requiredModules ) do
if not self._modulesLibrary[ name ] then
error( 'Отсутствует требуемый для элемента "'..elementType..'" модуль "'..name..'"' )
end
end
end
if parentId then
local parentElement = self._elements[ parentId ]
-- Проверка на наличие родительского элемента
if not parentElement then
error( 'Блока "'..parentId..'", указанного как родительский блок для блока "'..id..'", не существует' )
end
local parentElementType = parentElement.type
local parentElemetPattern = self._elementsLibrary[ parentElementType ]
-- Проверка на возможность родительского элемента иметь дочерние элементы
if not parentElemetPattern.children then
error( 'Блок "'..parentId..'" типа "'..parentElementType..'" не может иметь дочерних блоков' )
end
-- Проверка на уровень элементов
if elementPattern.children and elementPattern.level < parentElemetPattern.level then
error( 'Блок "'..id..'" типа "'..elementType..'" не может быть потомком блока "'..parentId..'" типа "'..parentElementType..'" по причине недостаточного уровня' )
end
end
end
--[[
modules = table -- Таблица модулей элемента.
elementType = string -- Тип элемента.
id = string -- Идентификатор элемента.
]]--
function navbox:_checkModules( modules, elementType, id )
local elementPattern = self._elementsLibrary[ elementType ]
for name, settings in pairs( modules ) do
local pattern = self._modulesLibrary[ name ]
-- Проверка на существование модуля
if not pattern then
error( 'Элемент "'..id..'". Модуль "'..name..'" не существует' )
end
-- Проверка на разрешенный тип элемента
local trueType
for i, permittedElement in ipairs( pattern.typesElements ) do
if permittedElement == elementType or permittedElement == elementPattern.sample then
trueType = true
end
end
if not trueType then
error( 'Элемент "'..id..'". Элементы типа "'..elementType..'" не совместимы с модулем "..name.."' )
end
-- Проверка настроек
local isTrueSettings, errorText = pattern.checkSettings( settings )
if not isTrueSettings then
if errorText then
error( 'Элемент "'..id..'" Неверные настройки модуля"'..name..'" '..errorText )
else
error( 'Элемент "'..id..'" Неверные настройки модуля"'..name..'"' )
end
end
end
-- Проверка наличия требуемых модулей
for i, requiredModule in ipairs( elementPattern.requiredModules ) do
if not modules[ requiredModule ] then
error( 'Элемент "'..id..'". Для модуля "'..requiredModule..'" отсутствуют требуемые модули' )
end
end
-- Проверка отсутствия запрещенных модулей
for i, incompatibleModule in ipairs( elementPattern.incompatibleModules ) do
if modules[ incompatibleModule ] then
error( 'Элемент "'..id..'". Присутствует запрещенный для модуля "'..requiredModule..'" модуль' )
end
end
end
--[[
billet = table -- заготовка элемента
{
text = string, -- текстовое содержимое элемента
type = string, -- тип элемента
id = string, -- идентификатор элемента,
attributes = table --(?) аттрибуты элемента
{
classes = string, --(?) css классы обертки навбокса,
styles = string, --(?) css стили обертки навбокса,
attrs = string --(?) HTML атрибуты обертки навбокса,
},
modules = table --(?) таблица модулей элемента
}
parentId = string -- идентификатор элемента, который должен быть родительским добавляемому
]]--
function navbox:_collectBillet( billet, parentId )
local type = billet.type
local parentElement
if parentId then
parentElement = self._elements[ parentId ]
end
if self._elementsLibrary[ type ].children then
billet.children = {}
if parentId and type == parentElement.type then
billet.nesting = parentElement.nesting + 1
else
billet.nesting = 1
end
end
if not parentId then
billet.level = 1
table.insert( self._elementsRoot, billet )
else
billet.parent = parentElement
billet.level = parentElement.level + 1
table.insert( parentElement.children, billet )
end
self._elements[ billet.id ] = billet
end
--
function navbox:assembly()
if self._navbox then
error( 'Навбокс закрыт для редактирования' )
end
local wrapper = mw.html.create( 'div' )
if self._attributes then
self:_applyAttrs( wrapper, self._attributes )
end
wrapper:addClass( 'navbox_wrapper' )
for i, child in ipairs( self._elementsRoot ) do
local block = self:_assembly( child )
wrapper:node( block )
end
self._navbox = wrapper
return wrapper
end
--[[
billet = table -- заготовка элемента
{
text = string, -- текстовое содержимое элемента
type = string, -- тип элемента
id = string, -- идентификатор элемента
attributes = table --(?) аттрибуты элемента
{
classes = string, --(?) css классы обертки навбокса,
styles = string --(?), css стили обертки навбокса,
attrs = HTML атрибуты обертки навбокса,
},
modules = table, --(?) таблица модулей элемента
children = table, --(?) заготовки дочерних элементов
nesting = number, --(?) глубина вложенности в однотипные элементы
level = number, --(?) глобальный уровень вложенности
parent = table --(?) заготовка родительского элемента
}
]]--
function navbox:_assembly( billet )
local text = billet.text
local attributes = billet.attributes
if billet.modules then
for i, modul in ipairs( billet.modules ) do
local attrs
text, attrs = self._modulesLibrary[ modul._name ].modify( text, modul )
--self:_applyAttrs( element, attributes )
end
end
local childBlocks = {}
if billet.children then
for i, child in ipairs( billet.children ) do
local childBlock = self:_assembly( child )
table.insert( childBlocks, childBlock )
end
end
element = self._elementsLibrary[ billet.type ].create( billet.text, childBlocks )
if attributes then
self:_applyAttrs( element, attributes )
end
if billet.nesting then
element:addClass( 'navbox_'..billet.type..'_n'..billet.nesting )
end
return element
end
--[[
elements = table -- таблица добавляемых элементов
replace = boolean --(?) заменять ли имеющиеся элементы
]]--
function navbox:addElements( elements, replace )
if replace and #self._elementsRoot ~= 0 then
error( 'Замена элементов невозможна. Навбокс уже отредактирован' )
end
local library = self._elementsLibrary
for name, element in pairs( elements ) do
if replace or not library[ name ] then
library[ name ] = element
end
end
end
--[[
elem = htmlObject -- элемент, к которому применяются аттрибуды
attrs = table -- применяемые аттрибуты
]]--
function navbox:_applyAttrs( elem, attrs )
if attrs.classes then
for i, class in ipairs( attrs.classes ) do
elem:addClass( class )
end
end
if attrs.styles then
elem:css( attrs.styles )
end
if attrs.attrs then
elem:attr( attrs.attrs )
end
end
--
function navbox:getBlockInfo( blockId )
if not blockId or not self._elems[ blockId ] then
return false
end
local block = self._elems[ blockId ]
local info = {}
info.nesting = block.nesting
info.level = block.level
info.blockType = block.blockType
info.id = blockId
if block.parent then
info.parentId = block.parent.id
end
info.children = {}
for i, child in ipairs( block.children ) do
info.children[ #info.children + 1 ] = child.id
end
return info
end
--
function navbox:checkBlock( blockId )
if blockId and self._elems[ blockId ] then
return true
end
return false
end
--
function navbox:getNavbox()
if not self._navbox then
error( 'Навбокс не готов' )
end
return self._navbox
end
--
function navbox:createSection( text, id, parentId, settings )
self:addElement( {type='section', text=text, id=id, parentId=parentId, attributes=settings} )
end
--
function navbox:createPartition( text, id, parentId, settings )
self:addElement( {type='partition', text=text, id=id, parentId=parentId, attributes=settings} )
end
--
function navbox:createContent( text, id, parentId, settings )
self:addElement( {type='content', text=text, id=id, parentId=parentId, attributes=settings} )
end
--
return navbox