|
|
Line 1: |
Line 1: |
| local p = {} | | local p = {}; |
|
| |
|
| local HtmlBuilder = require('Module:HtmlBuilder') | | local yesno = require('Module:Yesno') |
|
| |
|
| local args = {} | | local function _renderLine( frame, args, i ) |
| local origArgs | | if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] == '-' then |
| local argsAliases = {} | | return '' |
| local root
| | elseif args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then |
| | local style = ( args[ 'стиль_заголовков' ] or '' ) .. ( args[ 'стиль_заголовка' .. i ] or '' ); |
| | local class = ( args[ 'класс' .. i ] or '' ); |
| | return '\n<tr>\n<th colspan="2" scope="colgroup" class="infobox-header ' .. class .. '" style="' .. style .. '">' .. |
| | args[ 'заголовок' .. i ] .. |
| | '</th>\n</tr>'; |
| | end |
| | |
| | if args[ 'блок' .. i ] and args[ 'блок' .. i ] ~= '' then |
| | return args[ 'блок' .. i ]; |
| | end |
|
| |
|
| local function union(t1, t2) | | local text = args[ 'текст' .. i ] or ''; |
| -- Возвращает объединение значений двух таблиц в виде последовательности.
| | if args[ 'викиданные' .. i ] and args[ 'викиданные' .. i ] ~= '' then |
| local vals = {}
| | text = frame:expandTemplate{ title = 'Wikidata', args = { |
| for k, v in pairs(t1) do
| | args[ 'викиданные' .. i ], |
| vals[v] = true
| | text, |
| end
| | from = args[ 'from' ] or '' |
| for k, v in pairs(t2) do
| | } }; |
| vals[v] = true
| | end |
| end
| |
| local ret = {}
| |
| for k, v in pairs(vals) do
| |
| table.insert(ret, k)
| |
| end
| |
| return ret
| |
| end | |
|
| |
|
| local function getArgNums(prefix)
| | if text ~= '' then |
| -- Возвращает таблицу индексов существующих полей с заданным префиксом, | | local label = args[ 'метка' .. i ] or ''; |
| -- например, для префикса 'текст' и установленных 'текст1', 'текст2' и
| |
| -- 'текст5' возвращает {1, 2, 5}.
| |
| local nums = {}
| |
| for k, v in pairs(args) do
| |
| local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
| |
| if num then table.insert(nums, tonumber(num)) end
| |
| end
| |
| table.sort(nums)
| |
| return nums
| |
| end
| |
|
| |
|
| local function addRow(rowArgs) | | local class = args[ 'класс' .. i ] or ''; |
| -- Добавляет строку в карточку (заголовок или метку/текст).
| | if string.find(class, 'noplainlist') == nil and string.find(class, 'nofirstlevel') == nil then |
| if rowArgs.header then
| | class = class .. ' plainlist'; |
| root
| | end |
| .tag('tr')
| | if class ~= '' then |
| .addClass(rowArgs.rowclass)
| | class = ' class="' .. class .. '"'; |
| .attr('id', rowArgs.rowid)
| | end |
| .tag('th')
| |
| .attr('colspan', 2)
| |
| .attr('id', rowArgs.headerid)
| |
| .addClass(rowArgs.class)
| |
| .addClass(args['класс_заголовков'])
| |
| .css('text-align', 'center')
| |
| .cssText(args['стиль_заголовков'])
| |
| .wikitext(rowArgs.header)
| |
| elseif rowArgs.data then
| |
| local row = root.tag('tr')
| |
| row.addClass(rowArgs.rowclass)
| |
| row.attr('id', rowArgs.rowid)
| |
| if rowArgs.label then
| |
| row
| |
| .tag('th')
| |
| .attr('scope', 'row')
| |
| .attr('id', rowArgs.labelid)
| |
| .cssText(args['стиль_меток'])
| |
| .wikitext(rowArgs.label)
| |
| .done()
| |
| end
| |
|
| |
|
| local dataCell = row.tag('td')
| | local style = ( args[ 'стиль_текстов' ] or '' ) .. ( args[ 'стиль_текста' ] or '' ) .. ( args[ 'стиль_текста' .. i ] or '' ); |
| if not rowArgs.label then
| | if label == '' then |
| dataCell
| | style = 'text-align:center;' .. style; |
| .attr('colspan', 2)
| | end |
| .css('text-align', 'center')
| | if style ~= '' then |
| end
| | style = ' style="' .. style .. '"'; |
| dataCell
| | end |
| .attr('id', rowArgs.dataid)
| |
| .addClass(rowArgs.class)
| |
| .cssText(rowArgs.datastyle)
| |
| .newline()
| |
| .wikitext(rowArgs.data)
| |
| end
| |
| end | |
|
| |
|
| local function renderTitle() | | if label ~= '' then |
| if not args['название'] then return end
| | local labelClass = args[ 'класс_меток' ] or ''; |
| | if string.find(labelClass, 'noplainlist') == nil and string.find(labelClass, 'nofirstlevel') == nil then |
| | labelClass = labelClass .. ' plainlist'; |
| | end |
| | if labelClass ~= '' then |
| | labelClass = ' class="' .. labelClass .. '"'; |
| | end |
| | |
| | local labelStyle = ( args[ 'стиль_меток' ] or '' ) .. ( args[ 'стиль_метки' .. i ] or '' ); |
| | if labelStyle ~= '' then |
| | labelStyle = ' style="' .. labelStyle .. '"'; |
| | end |
|
| |
|
| root
| | return '\n<tr>\n<th scope="row"' .. labelClass .. labelStyle .. '>' .. label .. '</th>' .. |
| .tag('caption')
| | '\n<td' .. class .. style .. '>\n' .. text .. '</td>\n</tr>'; |
| .addClass(args['класс_названия'])
| | end |
| .cssText(args['стиль_названия'])
| | |
| .wikitext(args['название'])
| | return '\n<tr>\n<td colspan="2"' .. class .. style .. '>\n' .. text .. '</td>\n</tr>'; |
| | end |
| | |
| | return ''; |
| end | | end |
|
| |
|
| local function renderAboveRow() | | local function maxNumber ( args ) |
| if not args['вверху'] then return end
| | local maxNumber = 0 |
| | | for argName, _ in pairs(args) do |
| root
| | local argNumber = mw.ustring.match(argName, '^[^0-9]+([0-9]+)$') |
| .tag('tr')
| | if argNumber and tonumber(argNumber) > maxNumber then |
| .tag('th')
| | maxNumber = tonumber(argNumber) |
| .attr('colspan', 2)
| | end |
| .addClass(args['класс_вверху'])
| | end |
| .css('text-align', 'center')
| | return maxNumber |
| .css('font-size', '125%')
| |
| .css('font-weight', 'bold')
| |
| .cssText(args['стиль_вверху'])
| |
| .wikitext(args['вверху'])
| |
| end | | end |
|
| |
|
| local function renderAbove2Row()
| | function p.renderLine( frame ) |
| if not args['вверху2'] then return end
| | local args = frame:getParent().args; |
| | | return _renderLine(frame, args, '') |
| root
| |
| .tag('tr')
| |
| .tag('th')
| |
| .attr('colspan', 2)
| |
| .addClass(args['класс_вверху2'])
| |
| .css('text-align', 'center')
| |
| .css('font-style', 'oblique')
| |
| .cssText(args['стиль_вверху2'])
| |
| .wikitext(args['вверху2'])
| |
| end | | end |
|
| |
|
| local function renderBelowRow()
| | function p.renderLines( frame ) |
| if not args['внизу'] then return end
| | local args = frame:getParent().args; |
| | | |
| root
| | local res = '' |
| .tag('tr')
| | local header, text = '', '' |
| .tag('td')
| | |
| .attr('colspan', 2)
| | local autoHeaders = yesno(args [ 'автозаголовки' ] or 'false', false) |
| .addClass(args['класс_внизу'])
| |
| .css('text-align', 'center')
| |
| .cssText(args['стиль_внизу'])
| |
| .newline()
| |
| .wikitext(args['внизу'])
| |
| end
| |
| | |
| local function renderSubheaders() | |
| if args['подзаголовок'] then
| |
| args['подзаголовок1'] = args['подзаголовок']
| |
| end
| |
| if args['класс_ряда_подзаголовка'] then
| |
| args['класс_ряда_подзаголовка1'] = args['класс_ряда_подзаголовка']
| |
| end
| |
| local subheadernums = getArgNums('подзаголовок')
| |
| for k, num in ipairs(subheadernums) do
| |
| addRow({
| |
| data = args['подзаголовок' .. tostring(num)],
| |
| datastyle = args['стиль_подзаголовков'] or args['стиль_подзаголовка' .. tostring(num)],
| |
| class = args['класс_подзаголовков'],
| |
| rowclass = args['класс_ряда_подзаголовка' .. tostring(num)]
| |
| })
| |
| end
| |
| end
| |
| | |
| local function renderImages() | |
| if args['изображение'] then
| |
| args['изображение1'] = args['изображение']
| |
| end
| |
| if args['подпись'] then
| |
| args['подпись1'] = args['подпись']
| |
| end
| |
| local imagenums = getArgNums('изображение')
| |
| for k, num in ipairs(imagenums) do
| |
| local caption = args['подпись' .. tostring(num)]
| |
| local data = HtmlBuilder.create().wikitext(args['изображение' .. tostring(num)])
| |
| if caption then
| |
| data
| |
| .tag('div')
| |
| .cssText(args['стиль_подписи'])
| |
| .wikitext(caption)
| |
| end
| |
| addRow({
| |
| data = tostring(data),
| |
| datastyle = args['стиль_изображения'],
| |
| class = args['класс_изображения'],
| |
| rowclass = args['класс_ряда_изображения' .. tostring(num)]
| |
| })
| |
| end
| |
| end
| |
| | |
| local function renderRows()
| |
| -- Объединяет индексы заголовков и текстовых строк карточки
| |
| -- и визуализирует их в правильном порядке через addRow.
| |
| local rownums = union(getArgNums('заголовок'), getArgNums('текст'))
| |
| table.sort(rownums)
| |
| for k, num in ipairs(rownums) do
| |
| addRow({
| |
| header = args['заголовок' .. tostring(num)],
| |
| label = args['метка' .. tostring(num)],
| |
| data = args['текст' .. tostring(num)],
| |
| datastyle = args['стиль_текста'],
| |
| class = args['класс' .. tostring(num)],
| |
| rowclass = args['класс_ряда' .. tostring(num)],
| |
| dataid = args['id_текста' .. tostring(num)],
| |
| labelid = args['id_метки' .. tostring(num)],
| |
| headerid = args['id_заголовка' .. tostring(num)],
| |
| rowid = args['id_ряда' .. tostring(num)]
| |
| })
| |
| end
| |
| end
| |
| | |
| local function renderNavBar()
| |
| if not args['имя'] then return end
| |
| | |
| root
| |
| .tag('tr')
| |
| .tag('td')
| |
| .attr('colspan', 2)
| |
| .css('text-align', 'right')
| |
| .wikitext(mw.getCurrentFrame():expandTemplate({
| |
| title = 'Tnavbar',
| |
| args = { args['имя'] }
| |
| }))
| |
| end
| |
| | |
| local function isSet(x) | |
| -- Возвращает истину, если x задан и не пустой
| |
| -- Внимание: отличается от enwiki! В enwiki проверяется на равенство 'yes'
| |
| return x and x ~= ''
| |
| end
| |
| | |
| local function renderItalicTitle()
| |
| -- Внимание: отличается от enwiki. В enwiki ожидается yes или force, здесь работает любое значение
| |
| if isSet(args['заголовок_курсивом']) then
| |
| root.wikitext(mw.getCurrentFrame():expandTemplate({title = 'Заголовок курсивом'}))
| |
| end
| |
| end
| |
| | |
| local function renderTrackingCategories()
| |
| if not isSet(args.nocat) then
| |
| if #(getArgNums('текст')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
| |
| root.wikitext('[[Категория:Статьи с карточкой без заполненных данных]]')
| |
| end
| |
| if isSet(args['внедрение']) and args['название'] then
| |
| root.wikitext('[[Категория:Статьи со встроенной карточкой и параметром названия]]')
| |
| end
| |
| end
| |
| end
| |
| | |
| local function _infobox()
| |
| -- Задание общей страктуры карточки с добавлением стилей
| |
| -- для карточек-потомков.
| |
| if not isSet(args['внедрение']) then
| |
| root = HtmlBuilder.create('table')
| |
| | |
| root
| |
| .addClass('infobox')
| |
| .addClass(args['класс_тела'])
| |
| | |
| if isSet(args['подкарточка']) then
| |
| root
| |
| .css('padding', '0')
| |
| .css('border', 'none')
| |
| .css('margin', '-2px')
| |
| .css('width', 'auto')
| |
| .css('min-width', '100%')
| |
| .css('font-size', '100%')
| |
| .css('clear', 'none')
| |
| .css('float', 'none')
| |
| .css('background-color', 'transparent')
| |
| end
| |
|
| |
| -- Микроразметка
| |
| if isSet(args['микр_тела']) then
| |
| root
| |
| .attr('itemscope', 'itemscope')
| |
| .attr('itemtype', args['микр_тела'])
| |
| end
| |
|
| |
| root
| |
| .cssText(args['стиль_тела'])
| |
| | |
| renderTitle()
| |
| renderAboveRow()
| |
| renderAbove2Row()
| |
| else
| |
| root = HtmlBuilder.create()
| |
| | |
| root
| |
| .wikitext(args['название'])
| |
| end
| |
| | |
| renderSubheaders()
| |
| renderImages()
| |
| renderRows()
| |
| renderBelowRow()
| |
| renderNavBar()
| |
| renderItalicTitle()
| |
| renderTrackingCategories()
| |
| | |
| return tostring(root)
| |
| end
| |
| | |
| local function preprocessSingleArg(argName)
| |
| -- Добавляет аргумент в таблицу аргументов, если он определён и не пустой.
| |
| -- Пустые аргументы не обрабатываются, как и в ParserFunctions.
| |
| if origArgs[argName] and origArgs[argName] ~= '' then
| |
| args[argName] = origArgs[argName]
| |
| end
| |
| end
| |
| | |
| local function translateArg(aliasArgName,localArgName)
| |
| -- Функция добавляет поддержку алиасов параметров (например, на другом языке)
| |
| | | |
| -- Добавляем алиас параметра в таблицу алиасов | | for i = 1, maxNumber(args) do |
| -- Для одного параметра может быть несколько алиасов
| | if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then |
| -- Нумерованные параметры(текст1 и т.д.) заносятся без номера
| | if text ~= '' or not autoHeaders then |
| if not argsAliases[localArgName] then | | res = res .. header .. text |
| argsAliases[localArgName] = {} | | end |
| | header, text = _renderLine(frame, args, i), '' |
| | else |
| | text = text .. _renderLine(frame, args, i) |
| | end |
| | end |
| | if text ~= '' or not autoHeaders then |
| | res = res .. header .. text |
| end | | end |
| table.insert(argsAliases[localArgName], aliasArgName)
| |
| | | |
| -- Пока для тестирования: значения алиасов добавляются в таблицу аргументов | | return res |
| -- Нумерованные параметры работать не будут
| |
| if origArgs[localArgName] and origArgs[localArgName] ~= '' then
| |
| -- параметр уже задан на локальном языке
| |
| else
| |
| -- если алиас задан и не пустой
| |
| if origArgs[aliasArgName] and origArgs[aliasArgName] ~= '' then
| |
| origArgs[localArgName] = origArgs[aliasArgName]
| |
| end
| |
| end
| |
| end
| |
| | |
| local function preprocessArgs(prefixTable, step)
| |
| -- Сохраняет параметры с заданными префиксами в таблицу args, последовательно обходя
| |
| -- аргументы в нужном порядке и с нужным шагом. Благодаря этому сноски и пр. появляются
| |
| -- в правильном порядке. prefixTable — массив таблиц, каждая из которых может содержать
| |
| -- два поля: поле-строку префикса (обязательно) и поле-таблицу зависимых параметров.
| |
| -- Эта функция всегда обрабатывает параметры с префиксом, но зависимые параметры
| |
| -- обрабатываются, только если параметр с префиксом задан и не пустой.
| |
| if type(prefixTable) ~= 'table' then
| |
| error("В качестве таблицы префиксов должна использоваться таблица", 2)
| |
| end
| |
| if type(step) ~= 'number' then
| |
| error("Недопустимый тип параметра шага", 2)
| |
| end
| |
| | |
| -- Проверка правильности данных и обработка параметров без суффиксов.
| |
| for i,v in ipairs(prefixTable) do
| |
| if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
| |
| error('Недопустимая таблица префиксов preprocessArgs', 2)
| |
| end
| |
| preprocessSingleArg(v.prefix)
| |
| -- Зависимые параметры обрабатываются, только если параметр с префиксом задан и не пустой.
| |
| if args[v.prefix] and v.depend then
| |
| for j, dependValue in ipairs(v.depend) do
| |
| if type(dependValue) ~= 'string' then
| |
| error('Недопустимый тип зависимого параметра в таблице preprocessArgs')
| |
| end
| |
| preprocessSingleArg(dependValue)
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Обход нумерованных аргументов.
| |
| local a = 1 -- Переменная-счётчик.
| |
| local moreArgumentsExist = true
| |
| while moreArgumentsExist == true do
| |
| moreArgumentsExist = false
| |
| for i = a, a + step - 1 do
| |
| for j,v in ipairs(prefixTable) do
| |
| local prefixArgName = v.prefix .. tostring(i)
| |
| if origArgs[prefixArgName] then
| |
| moreArgumentsExist = true -- Искать аргументы дальше, если был хотя бы один (в т. ч. пустой)
| |
| preprocessSingleArg(prefixArgName)
| |
| end
| |
| -- Обрабатываем зависимые аргументы, если определена таблица зависимостей,
| |
| -- а также задан не пустой аргумент с префиксом, либо обрабатывается
| |
| -- "префикс1" и "префикс" задан (например, "изображение1" является синонимом для "изображение").
| |
| if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
| |
| for j,dependValue in ipairs(v.depend) do
| |
| local dependArgName = dependValue .. tostring(i)
| |
| preprocessSingleArg(dependArgName)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| a = a + step
| |
| end
| |
| end
| |
| | |
| function p.infobox(frame)
| |
| -- При запуске через #invoke аргументы передаются через стандартную систему.
| |
| -- При тестировании также можно передавать таблицу аргументов через frame.
| |
| if frame == mw.getCurrentFrame() then
| |
| origArgs = frame:getParent().args
| |
| else
| |
| origArgs = frame
| |
| end
| |
|
| |
| -- Поддержка параметров из англовики
| |
| translateArg('child','внедрение')
| |
| translateArg('bodyclass','класс_тела')
| |
| translateArg('subbox','подкарточка')
| |
| translateArg('bodystyle','стиль_тела')
| |
| translateArg('title','название')
| |
| translateArg('titleclass','класс_названия')
| |
| translateArg('titlestyle','стиль_названия')
| |
| translateArg('above','вверху')
| |
| translateArg('aboveclass','класс_вверху')
| |
| translateArg('abovestyle','стиль_вверху')
| |
|
| |
| translateArg('subheader','подзаголовок')
| |
| translateArg('subheaderrowstyle','стиль_подзаголовка')
| |
| translateArg('subheaderrowclass','класс_подзаголовка')
| |
| | |
| translateArg('subheaderstyle','стиль_подзаголовков')
| |
| translateArg('subheaderclass','класс_подзаголовков')
| |
| | |
| | |
| translateArg('image','изображение')
| |
| translateArg('caption','подпись')
| |
| translateArg('imagerowclass','класс_ряда_изображения')
| |
| | |
| translateArg('captionstyle','стиль_подписи')
| |
| translateArg('imagestyle','стиль_изображения')
| |
| translateArg('imageclass','класс_изображения')
| |
|
| |
| | |
| translateArg('header','заголовок')
| |
| translateArg('data','текст')
| |
| translateArg('label','метка')
| |
| translateArg('rowclass','класс_ряда')
| |
| translateArg('class','класс')
| |
| translateArg('dataid','id_текста')
| |
| translateArg('labelid','id_метки')
| |
| translateArg('headerid','id_заголовка')
| |
| translateArg('rowid','id_ряда')
| |
| | |
| translateArg('headerclass','класс_заголовков')
| |
| translateArg('headerstyle','стиль_заголовков')
| |
| translateArg('labelstyle','стиль_меток')
| |
| translateArg('datastyle','стиль_текста')
| |
| translateArg('below','внизу')
| |
| translateArg('belowclass','класс_внизу')
| |
| translateArg('belowstyle','стиль_внизу')
| |
| translateArg('name','имя')
| |
| --translateArg('italic title','заголовок_курсивом')
| |
| --translateArg('','')
| |
|
| |
| | |
| -- Параметры обрабатываются по направлению чтения карточки, чтобы
| |
| -- сноски и др. отображались в нужных местах. Параметры, зависящие
| |
| -- от других параметров, обрабатываются только при наличии других параметров,
| |
| -- чтобы в списке сносок не возникали нежелательные сноски.
| |
| preprocessSingleArg('внедрение')
| |
| preprocessSingleArg('класс_тела')
| |
| preprocessSingleArg('подкарточка')
| |
| preprocessSingleArg('стиль_тела')
| |
| preprocessSingleArg('название')
| |
| preprocessSingleArg('класс_названия')
| |
| preprocessSingleArg('стиль_названия')
| |
| preprocessSingleArg('вверху')
| |
| preprocessSingleArg('класс_вверху')
| |
| preprocessSingleArg('стиль_вверху')
| |
| preprocessSingleArg('вверху2')
| |
| preprocessSingleArg('класс_вверху2')
| |
| preprocessSingleArg('стиль_вверху2')
| |
| preprocessArgs({
| |
| {prefix = 'подзаголовок', depend = {'стиль_подзаголовка', 'класс_подзаголовка'}}
| |
| }, 10)
| |
| preprocessSingleArg('стиль_подзаголовков')
| |
| preprocessSingleArg('класс_подзаголовков')
| |
| preprocessArgs({
| |
| {prefix = 'изображение', depend = {'подпись', 'класс_ряда_изображения'}}
| |
| }, 10)
| |
| preprocessSingleArg('стиль_подписи')
| |
| preprocessSingleArg('стиль_изображения')
| |
| preprocessSingleArg('класс_изображения')
| |
| preprocessArgs({
| |
| {prefix = 'заголовок'},
| |
| {prefix = 'текст', depend = {'метка'}},
| |
| {prefix = 'класс_ряда'},
| |
| {prefix = 'класс'},
| |
| {prefix = 'id_текста'},
| |
| {prefix = 'id_метки'},
| |
| {prefix = 'id_заголовка'},
| |
| {prefix = 'id_ряда'}
| |
| }, 50)
| |
| preprocessSingleArg('класс_заголовков')
| |
| preprocessSingleArg('стиль_заголовков')
| |
| preprocessSingleArg('стиль_меток')
| |
| preprocessSingleArg('стиль_текста')
| |
| preprocessSingleArg('внизу')
| |
| preprocessSingleArg('класс_внизу')
| |
| preprocessSingleArg('стиль_внизу')
| |
| preprocessSingleArg('имя')
| |
| preprocessSingleArg('заголовок_курсивом')
| |
| preprocessSingleArg('nocat')
| |
| | |
| return _infobox()
| |
| end | | end |
|
| |
|
| return p | | return p; |