Модуль:ТранспортнаяСхема: различия между версиями

м Пока вырежу картинки
Нет описания правки
Строка 1: Строка 1:
local p = {}
local p = {}


-- Функция извлечения аргументов из прямого вызова и из шаблона
local function getArgs(frame)
local function getArgs(frame)
     local args = {}
     local args = {}
Строка 15: Строка 16:
end
end


-- Загрузка данных из data.json
local function loadData(args)
local function loadData(args)
     local dataParam = args['данные'] or args[1]
     local dataParam = args['данные'] or args[1]
Строка 36: Строка 38:
         if rawText and rawText ~= '' then
         if rawText and rawText ~= '' then
             rawText = mw.ustring.gsub(rawText, '<noinclude>.-</noinclude>', '')
             rawText = mw.ustring.gsub(rawText, '<noinclude>.-</noinclude>', '')
             rawText = mw.ustring.gsub(rawText, '<!--.--->', '')
             rawText = mw.ustring.gsub(rawText, '<!--.-?-->', '')
             rawText = mw.text.trim(rawText)
             rawText = mw.text.trim(rawText)
              
              
Строка 51: Строка 53:
end
end


local function getModeLabel(mode)
-- Генерация только интерактивной ImageMap карты
    local modes = {
function p.map(frame)
        metro = '🚇 Линии Муроморского метрополитена',
        train = '🚆 Направления Мурской железной дороги (МЖД)',
        other = '🚍 Прочие линии'
    }
    return modes[mode] or modes.other
end
 
function p.render(frame)
     local args = getArgs(frame)
     local args = getArgs(frame)
     local jsonData = loadData(args)
     local jsonData = loadData(args)
      
      
     local root = mw.html.create('div')
     local file = args['файл'] or args['изображение'] or jsonData.file or 'Схема_Муроморского_метрополитена.png'
        :addClass('ts-transport-scheme')
    local width = args['ширина'] or jsonData.width or '850px'
        :css({
    local alt = args['alt'] or args['название'] or jsonData.title or 'Схема скоростного транспорта'
            ['clear'] = 'both',
    local defaultRadius = args['радиус'] or jsonData.defaultRadius or '16'
            ['margin'] = '1.2em auto',
   
            ['width'] = '100%',
    local mapText = 'Файл:' .. file .. '|' .. width .. '|center|alt=' .. alt .. '\n'
            ['text-align'] = 'center'
    mapText = mapText .. '# Автоматически сгенерированная разметка станций\n'
        })
   
 
    if jsonData.lines then
    -- 1. Легенда линий и маршрутов
    if jsonData.lines and #jsonData.lines > 0 then
        local legend = root:tag('div')
            :addClass('ts-transport-lines-legend')
            :css({
                ['margin'] = '12px auto',
                ['max-width'] = '950px',
                ['padding'] = '8px 12px',
                ['background'] = '#f6f8fa',
                ['border'] = '1px solid #d0d7de',
                ['border-radius'] = '8px'
            })
 
        legend:tag('div')
            :css({
                ['font-size'] = '11px',
                ['font-weight'] = 'bold',
                ['color'] = '#57606a',
                ['text-transform'] = 'uppercase',
                ['margin-bottom'] = '6px'
            })
            :wikitext(jsonData.legendTitle or 'Линии скоростного транспорта')
 
        local legendBadges = legend:tag('div')
            :css({
                ['display'] = 'flex',
                ['flex-wrap'] = 'wrap',
                ['justify-content'] = 'center',
                ['gap'] = '5px'
            })
 
         for _, line in ipairs(jsonData.lines) do
         for _, line in ipairs(jsonData.lines) do
             local badge = legendBadges:tag('span')
             -- Зона названия / плашки линии (если задан box)
                 :css({
            if line.box and line.article then
                    ['display'] = 'inline-flex',
                 mapText = mapText .. 'rect ' .. line.box .. ' [[' .. line.article .. '|' .. (line.name or line.article) .. ']]\n'
                    ['align-items'] = 'center',
            end
                    ['padding'] = '2px 8px 2px 4px',
           
                    ['background'] = '#ffffff',
             -- Дополнительные произвольные полигоны линий (если есть)
                    ['border'] = '1px solid #d0d7de',
            if line.shapes then
                    ['border-radius'] = '20px',
                 for _, shape in ipairs(line.shapes) do
                    ['font-size'] = '12px'
                     mapText = mapText .. shape .. '\n'
                })
                end
 
            end
             badge:tag('span')
           
                 :css({
            -- Станции линии
                     ['display'] = 'inline-flex',
            if line.stations then
                    ['align-items'] = 'center',
                for _, st in ipairs(line.stations) do
                    ['justify-content'] = 'center',
                     if st.coords and st.article then
                    ['min-width'] = '16px',
                        local r = st.radius or defaultRadius
                    ['height'] = '16px',
                        mapText = mapText .. 'circle ' .. st.coords .. ' ' .. r .. ' [[' .. st.article .. '|' .. (st.name or st.article) .. ']]\n'
                    ['padding'] = '0 4px',
                    end
                    ['border-radius'] = '999px',
                end
                    ['background-color'] = line.color or '#888888',
            end
                    ['color'] = line.textColor or '#ffffff',
                     ['font-size'] = '9.5px',
                    ['font-weight'] = 'bold',
                    ['margin-right'] = '6px'
                })
                :wikitext(line.symbol or line.number or '')
 
            badge:tag('span')
                :wikitext('[[' .. (line.article or '') .. '|' .. (line.displayName or line.name or line.article or '') .. ']]')
         end
         end
     end
     end
 
      
     -- 2. Сворачиваемый каталог станций
     -- Дополнительные объекты (вокзалы, аэропорты)
     if jsonData.lines and #jsonData.lines > 0 then
    local extras = {'Вокзалы', 'Ж/д станции', 'Терминалы', 'Аэропорты'}
        local listCard = root:tag('div')
    for _, key in ipairs(extras) do
            :addClass('mw-collapsible toccolours')
        if jsonData[key] then
            :css({
             for _, item in ipairs(jsonData[key]) do
                ['margin'] = '12px auto 0 auto',
                 if item[1] and item[2] then
                ['max-width'] = '950px',
                    mapText = mapText .. 'circle ' .. item[2] .. ' ' .. defaultRadius .. ' ' .. item[1] .. '\n'
                ['text-align'] = 'left',
                ['background'] = 'var(--background-color-neutral-subtle, #f8f9fa)',
                ['border'] = '1px solid #d0d7de',
                ['border-radius'] = '8px',
                ['overflow'] = 'hidden'
            })
 
        listCard:tag('div')
            :css({
                ['font-weight'] = 'bold',
                ['font-size'] = '13.5px',
                ['background'] = 'linear-gradient(180deg, #f6f8fa 0%, #eaeef2 100%)',
                ['padding'] = '9px 14px',
                ['border-bottom'] = '1px solid #d0d7de'
            })
            :wikitext(jsonData.listTitle or '📋 Реестр станций')
 
        local listContent = listCard:tag('div')
            :addClass('mw-collapsible-content')
            :css({
                ['padding'] = '14px 18px',
                ['column-width'] = '20em',
                ['column-gap'] = '2em',
                ['column-rule'] = '1px solid #e1e4e8',
                ['font-size'] = '13px',
                ['line-height'] = '1.7'
            })
 
        local currentMode = nil
        local listWikitext = ''
 
        for _, line in ipairs(jsonData.lines) do
            local mode = line.mode or 'other'
            if mode ~= currentMode then
                currentMode = mode
                listWikitext = listWikitext .. "\n; " .. getModeLabel(mode) .. "\n"
            end
 
            listWikitext = listWikitext .. "* '''[[" .. (line.article or '') .. '|' .. (line.name or line.article or '') .. "]]'''\n"
             for _, station in ipairs(line.stations or {}) do
                 local badge = "<span style='display:inline-flex;align-items:center;justify-content:center;min-width:14px;height:14px;padding:0 3px;border-radius:999px;background:" .. (line.color or '#888') .. ";color:" .. (line.textColor or '#fff') .. ";font-size:9px;font-weight:bold;margin-right:4px;'>" .. (line.symbol or line.number or '') .. "</span>"
                listWikitext = listWikitext .. '** ' .. badge .. ' [[' .. station.article .. '|' .. (station.name or station.article) .. ']]'
                if station.transfer then
                    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'
             end
             end
         end
         end
        listContent:wikitext(listWikitext)
     end
     end
 
   
     return tostring(root)
    mapText = mapText .. 'desc none\n'
   
    -- Обработка через встроенный парсер MediaWiki тега <imagemap>
     return frame:preprocess('{{#tag:imagemap|' .. mapText .. '}}')
end
end


return p
return p