Модуль:ТранспортнаяСхема: различия между версиями
Tringoli (обсуждение | вклад) мНет описания правки |
Tringoli (обсуждение | вклад) мНет описания правки |
||
| Строка 1: | Строка 1: | ||
local p = {} | local p = {} | ||
-- Безопасная загрузка JSON | -- Универсальное слияние аргументов (из инфобокса, шаблона и вызова) | ||
local function loadData( | local function getArgs(frame) | ||
local dataParam = | local args = {} | ||
if frame.getParent then | |||
local parent = frame:getParent() | |||
if parent and parent.args then | |||
for k, v in pairs(parent.args) do args[k] = v end | |||
end | |||
end | |||
if frame.args then | |||
for k, v in pairs(frame.args) do args[k] = v end | |||
end | |||
return args | |||
end | |||
-- Безопасная загрузка JSON | |||
local function loadData(args) | |||
local dataParam = args['данные'] or args[1] | |||
if not dataParam or dataParam == '' then | if not dataParam or dataParam == '' then | ||
error('Не указано имя базы данных или страница JSON (параметр 1 или |данные=)') | error('Не указано имя базы данных или страница JSON (параметр 1 или |данные=)') | ||
| Строка 13: | Строка 28: | ||
end | end | ||
local success, jsonData = pcall(mw.loadJsonData, dataPageTitle) | local success, jsonData = pcall(mw.loadJsonData, dataPageTitle) | ||
if success and jsonData then | if success and jsonData then | ||
| Строка 19: | Строка 33: | ||
end | end | ||
local titleObj = mw.title.new(dataPageTitle) | local titleObj = mw.title.new(dataPageTitle) | ||
if titleObj and titleObj.exists then | if titleObj and titleObj.exists then | ||
| Строка 32: | Строка 45: | ||
return decodedData | return decodedData | ||
else | else | ||
error('Ошибка в синтаксисе JSON на странице [[' .. dataPageTitle .. ']]! | error('Ошибка в синтаксисе JSON на странице [[' .. dataPageTitle .. ']]!') | ||
end | end | ||
end | end | ||
end | end | ||
error('Страница данных [[' .. dataPageTitle .. ']] не найдена | error('Страница данных [[' .. dataPageTitle .. ']] не найдена.') | ||
end | end | ||
-- Генерация кода <imagemap> | -- Генерация кода <imagemap> с учётом ширины | ||
local function buildImageMap(jsonData, imageFile, width, defaultRadius) | local function buildImageMap(jsonData, imageFile, width, defaultRadius) | ||
local radius = defaultRadius or '16' | local radius = defaultRadius or '16' | ||
local mapText = 'Файл:' .. imageFile .. '|' .. width .. '|center|alt=' .. (jsonData.title or 'Схема | local mapText = 'Файл:' .. imageFile .. '|' .. width .. '|center|alt=' .. (jsonData.title or 'Схема транспорта') .. '\n' | ||
for _, line in ipairs(jsonData.lines or {}) do | for _, line in ipairs(jsonData.lines or {}) do | ||
| Строка 62: | Строка 75: | ||
end | end | ||
local function getModeLabel(mode) | local function getModeLabel(mode) | ||
local modes = { | local modes = { | ||
| Строка 72: | Строка 84: | ||
end | end | ||
function p.render(frame) | function p.render(frame) | ||
local args = frame | local args = getArgs(frame) | ||
local jsonData = loadData(args) | |||
local jsonData = loadData( | |||
local isInfobox = (args['карточка'] == 'да' or args['тип'] == 'карточка') | |||
local defaultWidth = isInfobox and '280px' or '850px' | local defaultWidth = isInfobox and '280px' or '850px' | ||
-- Ширина теперь строго приоритезирует параметр вызова, затем режим карточки | |||
local width = args['ширина'] or (isInfobox and '280px') or jsonData.width or '850px' | |||
local imageFile = args['файл'] or jsonData.image or 'Схема_Муроморского_метрополитена.png' | local imageFile = args['файл'] or jsonData.image or 'Схема_Муроморского_метрополитена.png' | ||
local caption = args['подпись'] or jsonData.caption or '' | local caption = args['подпись'] or jsonData.caption or '' | ||
local defaultRadius = args['радиус'] or jsonData.defaultRadius or '16' | local defaultRadius = args['радиус'] or jsonData.defaultRadius or '16' | ||
| Строка 97: | Строка 106: | ||
}) | }) | ||
-- | -- Контейнер карты | ||
local mapCard = root:tag('div') | local mapCard = root:tag('div') | ||
:addClass('ts-transport-map-card') | :addClass('ts-transport-map-card') | ||
| Строка 132: | Строка 141: | ||
end | end | ||
-- | -- Легенда и список выводятся только вне карточки инфобокса | ||
if not isInfobox then | if not isInfobox then | ||
if jsonData.lines and #jsonData.lines > 0 then | if jsonData.lines and #jsonData.lines > 0 then | ||
local legend = root:tag('div') | local legend = root:tag('div') | ||
| Строка 153: | Строка 161: | ||
['color'] = '#57606a', | ['color'] = '#57606a', | ||
['text-transform'] = 'uppercase', | ['text-transform'] = 'uppercase', | ||
['margin-bottom'] = '6px | ['margin-bottom'] = '6px' | ||
}) | }) | ||
:wikitext(jsonData.legendTitle or 'Линии скоростного транспорта') | :wikitext(jsonData.legendTitle or 'Линии скоростного транспорта') | ||
| Строка 200: | Строка 207: | ||
end | end | ||
if jsonData.lines and #jsonData.lines > 0 then | if jsonData.lines and #jsonData.lines > 0 then | ||
local listCard = root:tag('div') | local listCard = root:tag('div') | ||
| Строка 209: | Строка 215: | ||
['text-align'] = 'left', | ['text-align'] = 'left', | ||
['background'] = 'var(--background-color-neutral-subtle, #f8f9fa)', | ['background'] = 'var(--background-color-neutral-subtle, #f8f9fa)', | ||
['border'] = '1px solid | ['border'] = '1px solid #d0d7de', | ||
['border-radius'] = '8px', | ['border-radius'] = '8px', | ||
['overflow'] = 'hidden' | ['overflow'] = 'hidden' | ||
| Строка 220: | Строка 226: | ||
['background'] = 'linear-gradient(180deg, #f6f8fa 0%, #eaeef2 100%)', | ['background'] = 'linear-gradient(180deg, #f6f8fa 0%, #eaeef2 100%)', | ||
['padding'] = '9px 14px', | ['padding'] = '9px 14px', | ||
['border-bottom'] = '1px solid | ['border-bottom'] = '1px solid #d0d7de' | ||
}) | }) | ||
:wikitext(jsonData.listTitle or '📋 Реестр станций | :wikitext(jsonData.listTitle or '📋 Реестр станций') | ||
local listContent = listCard:tag('div') | local listContent = listCard:tag('div') | ||