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

мНет описания правки
Нет описания правки
Строка 16: Строка 16:
end
end


-- Загрузка данных из data.json
-- Загрузка данных из data.json с расширенным поиском
local function loadData(args)
local function loadData(args)
     local dataParam = args['данные'] or args[1] or 'Муроморского'
     local dataParam = args['данные'] or args[1] or 'Муроморского'
    local candidates = {
        dataParam,
        'Шаблон:Интерактивная схема ' .. dataParam .. ' метрополитена/data.json',
        'Шаблон:Интерактивная схема ' .. dataParam .. '/data.json',
        'Шаблон:' .. dataParam .. '/data.json',
        dataParam .. '/data.json'
    }
      
      
     for _, title in ipairs(candidates) do
     local candidates = {}
         local success, jsonData = pcall(mw.loadJsonData, title)
    local function addCandidate(title)
         if success and jsonData then return jsonData end
        if title and title ~= '' then
            for _, existing in ipairs(candidates) do
                if existing == title then return end
            end
            table.insert(candidates, title)
        end
    end
   
    -- Проверяем прямое имя, основное пространство и пространство Шаблон:
    addCandidate(dataParam)
    addCandidate(dataParam .. '/data.json')
    addCandidate('Шаблон:' .. dataParam)
    addCandidate('Шаблон:' .. dataParam .. '/data.json')
    addCandidate('Шаблон:Интерактивная схема ' .. dataParam .. '/data.json')
    addCandidate('Шаблон:Интерактивная схема ' .. dataParam .. ' метрополитена/data.json')
    addCandidate('Интерактивная схема ' .. dataParam .. '/data.json')
    addCandidate('Интерактивная схема ' .. dataParam .. ' метрополитена/data.json')
   
    local jsonErrors = {}
   
    for _, pageTitle in ipairs(candidates) do
        -- 1. Загрузка через mw.loadJsonData
         local ok, data = pcall(mw.loadJsonData, pageTitle)
         if ok and data and type(data) == 'table' then
            return data
        elseif not ok and data and not mw.ustring.find(tostring(data), 'does not exist') and not mw.ustring.find(tostring(data), 'не существует') then
            table.insert(jsonErrors, pageTitle .. ': ' .. tostring(data))
        end
          
          
         local titleObj = mw.title.new(title)
        -- 2. Загрузка текста через mw.title (если страница создана как вики-текст)
         local titleObj = mw.title.new(pageTitle)
         if titleObj and titleObj.exists then
         if titleObj and titleObj.exists then
             local raw = titleObj:getContent()
             local rawText = titleObj:getContent()
             if raw and raw ~= '' then
             if rawText and rawText ~= '' then
                 raw = mw.ustring.gsub(raw, '<noinclude>.-</noinclude>', '')
                 rawText = mw.ustring.gsub(rawText, '<noinclude>.-</noinclude>', '')
                 raw = mw.ustring.gsub(raw, '<!--.-?-->', '')
                 rawText = mw.ustring.gsub(rawText, '<!--.-?-->', '')
                 local ok, decoded = pcall(mw.text.jsonDecode, mw.text.trim(raw))
                rawText = mw.text.trim(rawText)
                 if ok and decoded then return decoded end
               
                 local decOk, decoded = pcall(mw.text.jsonDecode, rawText)
                 if decOk and decoded and type(decoded) == 'table' then
                    return decoded
                else
                    table.insert(jsonErrors, pageTitle .. ' (ошибка синтаксиса JSON: ' .. tostring(decoded) .. ')')
                end
             end
             end
         end
         end
     end
     end
     error('Страница данных JSON не найдена: ' .. dataParam)
   
    if #jsonErrors > 0 then
        error('Ошибка в синтаксисе JSON на найденной странице:\n* ' .. table.concat(jsonErrors, '\n* '))
    end
   
     error('Страница данных JSON не найдена. Убедитесь, что страница создана и сохранена под одним из названий:\n* [[' .. table.concat(candidates, ']]\n* [[') .. ']]')
end
end


Строка 52: Строка 84:
end
end


-- Генерация Canvas схемы с поддержкой масштабирования и кадрирования
-- Генерация Canvas схемы
function p.canvas(frame)
function p.canvas(frame)
     local args = getArgs(frame)
     local args = getArgs(frame)
     local data = loadData(args)
     local data = loadData(args)
      
      
    -- Базовый размер оригинального холста
     local origW = tonumber(args['ширина_оригинала'] or 850) or 850
     local origW = tonumber(args['ширина_оригинала'] or 850) or 850
     local origH = tonumber(args['высота_оригинала'] or 620) or 620
     local origH = tonumber(args['высота_оригинала'] or 620) or 620
      
      
    -- Параметры кадрирования (вырезки)
     local cropX, cropY, cropW, cropH = nil, nil, nil, nil
     local cropX, cropY, cropW, cropH = nil, nil, nil, nil
     if args['кадрирование'] or args['crop'] then
     if args['кадрирование'] or args['crop'] then
Строка 78: Строка 108:
     end
     end
      
      
    -- Результирующий масштаб и размеры блока
     local targetW = cropW or origW
     local targetW = cropW or origW
     local targetH = cropH or origH
     local targetH = cropH or origH
Строка 94: Строка 123:
     local finalBoxH = tonumber(args['высота_блока'] or args['высота_карточки'] or args['высота']) or (targetH * scale)
     local finalBoxH = tonumber(args['высота_блока'] or args['высота_карточки'] or args['высота']) or (targetH * scale)
      
      
    -- Внешний контейнер-обрезчик (Viewport)
     local wrapper = mw.html.create('div')
     local wrapper = mw.html.create('div')
         :addClass('ts-transport-map-viewport')
         :addClass('ts-transport-map-viewport')
Строка 113: Строка 141:
         })
         })
          
          
    -- Смещение внутри холста
     local shiftX = cropX or 0
     local shiftX = cropX or 0
     local shiftY = cropY or 0
     local shiftY = cropY or 0
      
      
    -- Внутренний трансформируемый холст
     local canvas = wrapper:tag('div')
     local canvas = wrapper:tag('div')
         :addClass('ts-html-transport-canvas')
         :addClass('ts-html-transport-canvas')
Строка 131: Строка 157:
         })
         })


    -- Шапка/логотип схемы (отключается параметром шапка=нет или при кадрировании)
     if not (args['шапка'] == 'нет' or cropX ~= nil) then
     if not (args['шапка'] == 'нет' or cropX ~= nil) then
         local header = canvas:tag('div')
         local header = canvas:tag('div')
Строка 163: Строка 188:
         header:tag('div')
         header:tag('div')
             :css({['text-align'] = 'left'})
             :css({['text-align'] = 'left'})
             :tag('div'):css({['font-weight'] = 'bold', ['font-size'] = '13px', ['color'] = '#1f2328'}):wikitext(data.title or 'Муроморский скоростной транспорт'):done()
             :tag('div'):css({['font-weight'] = 'bold', ['font-size'] = '13px', ['color'] = '#1f2328'}):wikitext(data.title or 'Скоростной транспорт'):done()
             :tag('div'):css({['font-size'] = '10px', ['color'] = '#57606a', ['text-transform'] = 'uppercase', ['letter-spacing'] = '0.5px'}):wikitext('Интерактивная схема линий'):done()
             :tag('div'):css({['font-size'] = '10px', ['color'] = '#57606a', ['text-transform'] = 'uppercase', ['letter-spacing'] = '0.5px'}):wikitext('Интерактивная схема линий'):done()
     end
     end


     if data.lines then
     if data.lines then
         -- 1. Слой путей (линий между станциями)
         -- Слой путей
         for _, line in ipairs(data.lines) do
         for _, line in ipairs(data.lines) do
             local color = line.color or '#888888'
             local color = line.color or '#888888'
Строка 204: Строка 229:
         end
         end


         -- 2. Слой станций и подписей
         -- Слой станций и подписей
         for _, line in ipairs(data.lines) do
         for _, line in ipairs(data.lines) do
             local color = line.color or '#888888'
             local color = line.color or '#888888'
Строка 215: Строка 240:
                     local isFuture = (st.future == true)
                     local isFuture = (st.future == true)
                      
                      
                    -- Кружок станции
                     local node = canvas:tag('div')
                     local node = canvas:tag('div')
                         :css({
                         :css({
Строка 233: Строка 257:
                     node:wikitext('[[' .. article .. '|<span style="display:block;width:100%;height:100%;" title="' .. name .. '"></span>]]')
                     node:wikitext('[[' .. article .. '|<span style="display:block;width:100%;height:100%;" title="' .. name .. '"></span>]]')
                      
                      
                    -- Текстовая подпись станции
                     local isRightSide = (x >= (origW / 2))
                     local isRightSide = (x >= 430)
                     local label = canvas:tag('div')
                     local label = canvas:tag('div')
                         :css({
                         :css({