Модуль:ТранспортнаяСхема: различия между версиями
Tringoli (обсуждение | вклад) ПОЕХАЛИ |
Tringoli (обсуждение | вклад) мНет описания правки |
||
| Строка 1: | Строка 1: | ||
local p = {} | local p = {} | ||
-- | -- Безопасная загрузка JSON из пространства Шаблонов | ||
local function loadData(frame) | local function loadData(frame) | ||
local | local dataParam = frame.args['данные'] or frame.args[1] | ||
if not | if not dataParam or dataParam == '' then | ||
error('Не | error('Не указано имя базы данных или страница JSON (параметр 1 или |данные=)') | ||
end | end | ||
if not mw.ustring.find( | local dataPageTitle = dataParam | ||
if not mw.ustring.find(dataParam, ':') then | |||
dataPageTitle = 'Шаблон:Интерактивная схема ' .. dataParam .. '/data.json' | |||
end | end | ||
local success, jsonData = pcall(mw.loadJsonData, | -- Способ 1: Стандартная загрузка через mw.loadJsonData (если тип контента страницы = JSON) | ||
if | local success, jsonData = pcall(mw.loadJsonData, dataPageTitle) | ||
if success and jsonData then | |||
return jsonData | |||
end | end | ||
return | |||
-- Способ 2: Резервная загрузка текста и декодирование (если страница сохранена как wikitext) | |||
local titleObj = mw.title.new(dataPageTitle) | |||
if titleObj and titleObj.exists then | |||
local rawText = titleObj:getContent() | |||
if rawText and rawText ~= '' then | |||
-- Очистка от возможных noinclude / комментариев | |||
rawText = mw.ustring.gsub(rawText, '<noinclude>.-</noinclude>', '') | |||
rawText = mw.ustring.gsub(rawText, '<!--.--->', '') | |||
rawText = mw.text.trim(rawText) | |||
local decodeSuccess, decodedData = pcall(mw.text.jsonDecode, rawText) | |||
if decodeSuccess and decodedData then | |||
return decodedData | |||
else | |||
error('Ошибка в синтаксисе JSON на странице [[' .. dataPageTitle .. ']]! Проверьте запятые и кавычки.') | |||
end | |||
end | |||
end | |||
error('Страница данных [[' .. dataPageTitle .. ']] не найдена. Убедитесь, что она создана.') | |||
end | end | ||
-- Генерация | -- Генерация кода <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 | ||
| Строка 41: | Строка 63: | ||
end | end | ||
-- | -- Названия категорий транспорта | ||
local function getModeLabel(mode) | local function getModeLabel(mode) | ||
local modes = { | local modes = { | ||
metro = '🚇 Линии Муроморского метрополитена', | metro = '🚇 Линии Муроморского метрополитена', | ||
train = '🚆 Направления Мурской железной дороги (МЖД)', | train = '🚆 Направления Мурской железной дороги (МЖД)', | ||
other = '🚍 Прочие линии' | |||
other = '🚍 Прочие | |||
} | } | ||
return modes[mode] or modes.other | return modes[mode] or modes.other | ||
end | end | ||
-- | -- Рендеринг схемы | ||
function p.render(frame) | function p.render(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
| Строка 62: | Строка 81: | ||
local jsonData = loadData(frame) | local jsonData = loadData(frame) | ||
local imageFile = args['файл'] or jsonData.image or ' | local imageFile = args['файл'] or jsonData.image or 'Схема_Муроморского_метрополитена.png' | ||
local width = args['ширина'] or jsonData.width or ' | local width = args['ширина'] or jsonData.width or '850px' | ||
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' | ||
| Строка 107: | Строка 126: | ||
end | end | ||
-- 2. Легенда линий | -- 2. Легенда линий | ||
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') | ||
| Строка 113: | Строка 132: | ||
:css({ | :css({ | ||
['margin'] = '12px auto', | ['margin'] = '12px auto', | ||
['max-width'] = ' | ['max-width'] = '950px', | ||
['padding'] = ' | ['padding'] = '8px 12px', | ||
['background'] = '#f6f8fa', | ['background'] = '#f6f8fa', | ||
['border'] = '1px solid #d0d7de', | ['border'] = '1px solid #d0d7de', | ||
| Строка 122: | Строка 141: | ||
legend:tag('div') | legend:tag('div') | ||
:css({ | :css({ | ||
['font-size'] = ' | ['font-size'] = '11px', | ||
['font-weight'] = 'bold', | ['font-weight'] = 'bold', | ||
['color'] = '#57606a', | ['color'] = '#57606a', | ||
['text-transform'] = 'uppercase', | ['text-transform'] = 'uppercase', | ||
['margin-bottom'] = ' | ['margin-bottom'] = '6px', | ||
['letter-spacing'] = '0.5px' | ['letter-spacing'] = '0.5px' | ||
}) | }) | ||
:wikitext(jsonData.legendTitle or 'Линии | :wikitext(jsonData.legendTitle or 'Линии скоростного транспорта') | ||
local legendBadges = legend:tag('div') | local legendBadges = legend:tag('div') | ||
| Строка 173: | Строка 192: | ||
end | end | ||
-- 3. Каталог станций | -- 3. Каталог станций | ||
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') | ||
| Строка 179: | Строка 198: | ||
:css({ | :css({ | ||
['margin'] = '12px auto 0 auto', | ['margin'] = '12px auto 0 auto', | ||
['max-width'] = ' | ['max-width'] = '950px', | ||
['text-align'] = 'left', | ['text-align'] = 'left', | ||
['background'] = 'var(--background-color-neutral-subtle, #f8f9fa)', | ['background'] = 'var(--background-color-neutral-subtle, #f8f9fa)', | ||
| Строка 195: | Строка 214: | ||
['border-bottom'] = '1px solid var(--border-color-base, #d0d7de)' | ['border-bottom'] = '1px solid var(--border-color-base, #d0d7de)' | ||
}) | }) | ||
:wikitext(jsonData.listTitle or '📋 Реестр | :wikitext(jsonData.listTitle or '📋 Реестр станций метрополитена и МЖД') | ||
local listContent = listCard:tag('div') | local listContent = listCard:tag('div') | ||
| Строка 224: | Строка 243: | ||
if station.transfer then | if station.transfer then | ||
listWikitext = listWikitext .. " <small style='color:#57606a;'>(" .. station.transfer .. ")</small>" | listWikitext = listWikitext .. " <small style='color:#57606a;'>(" .. station.transfer .. ")</small>" | ||
end | |||
if station.future then | |||
listWikitext = listWikitext .. " <small style='color:#8c959f; font-style:italic;'>(строит.)</small>" | |||
end | end | ||
listWikitext = listWikitext .. '\n' | listWikitext = listWikitext .. '\n' | ||