Модуль:Источники по теме
Подгружает ссылки на энциклопедии и братские википроекты из Викиданных и параметров шаблона-шапки и интерпретирует их, показывая в шапках статей.
Используется в Модуль:Отексте, Шаблон:Отексте, Модуль:Обавторе, Шаблон:Обавторе.
Использует:
- MediaWiki:Wikiprojects settings.json — настройки наименований википроектов.
- MediaWiki:Encyclopedias settings.json — настройки заголовков энциклопедий и их id в Викиданных.
- MediaWiki:Encyclopedias sites.json — настройки энциклопедий на внешних сайтах.
Подмодули:
- Модуль:Данные страницы — объект page, в который собираются данные по странице
- Модуль:Источники по теме/wikidata — сборщик данных из Викиданных
- Модуль:Источники по теме/Категоризация — выполняется на последнем этапе, работает по собранным и сортированным данным
- Модуль:Util — хелперы
Функции[править код]
p.get_data(frame)
— основная
local RU = 'ru' local WIKISOURCE = 'wikisource' local RUWIKISOURCE = 'ruwikisource' -- Приоритет выбора ссылок на интервики. Расставлены примерно по величине размера проекта и числу админов, с приоритетом для европ., и en-de/pl-uk языков. '*' — любая другая другая интервика local preferredLanguages = { RU, 'en', 'de', 'pl', 'uk', 'fr', 'it', 'es', 'cs', 'pt', 'da', 'sv', 'fi', 'ja', 'zh', 'he', 'ar', '*' } local p = {} local util = require("Module:Util") local wikidata = require("Модуль:Источники по теме/wikidata") local projects_cfg = util.get_json('MediaWiki:Wikiprojects settings.json') local encyclopediasData = util.get_json("MediaWiki:Encyclopedias settings.json") -- настройки заголовков энциклопедий и их id в ВД -- local encyclopedias_sites_cfg = util.get_json("MediaWiki:Encyclopedias sites.json") -- настройки энциклопедий на внеших сайтах local page = require("Модуль:Данные страницы").page function page:add_project(project, manual, wd, index) local d = p.set_priority_links(manual, wd) if not self.projects[index] then self.projects[index] = { label = self.sitelinks[index].label, id = self.sitelinks[index].id, links = {} } end table.insert(self.projects[index].links, { project = project, title = d.title, link = d.link, lang = d.lang, manual_link = manual.link, manual_lang = manual.lang, wd_link = wd.link, wd_lang = wd.lang }) end function page:add_enc(s) table.insert(self.enc_wikilinks, s) end page.enc_links_raw = {} -- Приоритет ссылок на википроекты: ручных ссылок или из ВД function p.set_priority_links(manual, wd) local data = {} if manual.link and wd.link then -- RU ссылки приоритетней из ВД -- Ручные обычно устарели на 5-10 лет, часто ведут на ошибочные, удалённые статьи или переделанные в неоднозначности -- Ссылка на интервики из ВД только если нет ручной ссылки. Поскольку ручная ссылка обычно точнее общей, указанной в preferredLanguages if wd.lang == RU then data = wd else for _, preflang in pairs(preferredLanguages) do if preflang ~= RU and preflang ~= '*' then if preflang == wd.link then data = wd break end end end end if data.link == nil then data = manual end elseif manual.link then data = manual elseif wd.link then data = wd end return data end -- сортировка интервик в формате [проект.язык.страница]. Без monolanguage-проектов. local function reshape_interwiki_by_projects(wikidataInterwiki) local interwiki_by_projects = {} for langprojectcode, title in pairs(wikidataInterwiki) do if title and langprojectcode ~= 'commonswiki' and langprojectcode ~= 'specieswiki' then for _, project in pairs(projects_cfg) do if not project.monolanguage then local project_code = project.project local lang = string.match(langprojectcode, '^(.*)' .. project_code .. '$') if is(lang) then if not interwiki_by_projects[project_code] then interwiki_by_projects[project_code] = {} end interwiki_by_projects[project_code][lang] = title break end end end end end return interwiki_by_projects end -- заполняет список `page.projects` local function make_list_projects_links() local args = page.args for index, section in ipairs(page.sitelinks) do local sitelinks = section.data --mw.logObject(sitelinks,"sitelinks") local sitelinks_by_projects = reshape_interwiki_by_projects(sitelinks) for _, project in pairs(projects_cfg) do local projectCode = project.project -- like 'wikisource' local prj_code = project.code local prj_sitelinks = sitelinks_by_projects[projectCode] local manual = { lang = nil, link = nil, title = nil } -- ссылки из аргумента шаблона local wd = { lang = nil, link = nil, title = nil } -- ссылка из Викиданных -- ручная ссылка в параметре шаблона local value = args[project.arg] -- значение параметра if is(value) then local lang, title = string.match(value, '^:?([a-z]+):(.+)') -- ссылка формата ':код_языка:Название' в параметрах if not title then lang, title = RU, value end if project.monolanguage then manual.lang, manual.title, manual.link = nil, title, util.make_interlink(prj_code, nil, title) else manual.lang, manual.title, manual.link = lang, title, util.make_interlink(prj_code, lang, title) end end -- поиск ссылки в Викиданных -- моноязычные проекты (Викисклад, Викивиды, Викиданные) if project.monolanguage then local title = sitelinks[projectCode] if projectCode == 'commons' and not title then title = sitelinks['commonswiki'] end if title then wd.title, wd.link = title, util.make_interlink(prj_code, nil, title) end -- мультиязычные проекты elseif prj_sitelinks then local foundProjectLink = false -- перебор предпочтительных языков preferredLanguages for _, preflang in pairs(preferredLanguages) do if preflang == '*' then -- языки под '*' в preferredLanguages for lang, title in pairs(prj_sitelinks) do if lang then -- and projectCode ~= WIKISOURCE -- ссылки на малоразвитые интерВикитеки не нужны wd.lang, wd.title, wd.link = lang, title, util.make_interlink(prj_code, lang, title) foundProjectLink = true break end end else -- языки не под '*' в preferredLanguages local lang = preflang local title = prj_sitelinks[lang] if title then wd.lang, wd.title, wd.link = lang, title, util.make_interlink(prj_code, lang, title) foundProjectLink = true end end if foundProjectLink then break end end if manual.link and manual.title then manual.title = mw.ustring.gsub(manual.title, '_', ' ') end end if manual.link or wd.link then page:add_project(project, manual, wd, index) elseif projectCode == 'wiki' then -- если нет ссылок на Википедию, то ссылка на Википедию по параметру ПОИСК local searchString = args['ПОИСК'] or page.frame1.args.search -- mw.logObject(page.projects, "page.projects") -- mw.logObject(index, "index") if searchString and #searchString > 0 then manual.link = ':w:Special:Search/' .. searchString manual.lang = RU page:add_project(project, manual, wd, index) end end end end -- mw.logObject(page, "page") return page end local function getPageTitleFromArgument(enc, title, isPRS) if enc.project ~= RUWIKISOURCE then return ':' .. enc.projectCode .. enc.prefix .. title .. enc.suffix end local linkVT = nil local linkDO = nil if enc.id == "Q1970746" then -- workaround для ручного параметра ТСД= linkVT = "ТСД/" .. title linkDO = linkVT .. "/ДО" else linkVT = string.gsub(enc.titleVT, "$1", title) if enc.titleDO then linkDO = string.gsub(enc.titleDO, "$1", title) end end if isPRS then if mw.title.new(linkDO, 0).exists then return linkDO elseif mw.title.new(linkVT, 0).exists then return linkVT else return linkDO end else if mw.title.new(linkVT, 0).exists then return linkVT elseif mw.title.new(linkDO, 0).exists then return linkDO else return linkVT end end end -- заполняет список `page.enc_wikilinks` викиссылками на энциклопедии local function make_list_encyclopedias_links(frame) local args = page.args local enc_links_raw = page.enc_links_raw for _, enc in pairs(encyclopediasData) do local dictArgName = enc.argument local id = enc.id local is_title_matches_enc_link = (enc.project == RUWIKISOURCE and (wikidata.is_match_pagenames(page.title, enc.titleVT) or (enc.titleDO and wikidata.is_match_pagenames(page.title, enc.titleDO)))) if not is_title_matches_enc_link then -- исключение страниц энциклопедий идентичных ссылке. TODO: Возможно это дублирует схожий метод из подмодуля ../wikidata : sitlinks[entity.id] = nil -- исключить id базовой энциклопедии local manual_links, wd_links = {}, {} -- ссылки из Викиданных local ids = page.encyclopedias_ids[dictArgName] if ids then for _, eid in pairs(ids) do local link = wikidata.getLink(enc, eid, page.isPRS) if link then table.insert(wd_links, link) end end end -- ссылки из параметров шаблона local value = args[dictArgName] if is(value) then for elem in mw.text.gsplit(value, '%s*~%s*') do -- несколько значений в одном параметре local link = getPageTitleFromArgument(enc, elem, page.isPRS) table.insert(manual_links, link) end end -- добавление ссылок if #manual_links > 0 or #wd_links > 0 then -- сырые ссылки, разделённые по источникам, используются ниже и для категоризации enc_links_raw[dictArgName] = { manual_links = manual_links, wd_links = wd_links, enc = enc } -- викификация и фильтрация ссылок -- любые из шаблона, могут включать ссылки с якорями # for _, mlink in pairs(manual_links) do page:add_enc(util.make_wikilink(mlink, enc.title)) end -- из Викиданных, исключая дубли шаблонных ссылок и содержащие # for _, wlink in pairs(wd_links) do local wlink_eq_mlink = false for _, mlink in pairs(manual_links) do if mlink == wlink or mw.ustring.match(mlink, '^(.+)#') then wlink_eq_mlink = true break end end if not wlink_eq_mlink then page:add_enc(util.make_wikilink(wlink, enc.title)) end end end end end -- внешние сайты for enc_name, site in pairs(page.external_sites) do page:add_enc(site.wikilink) end -- mw.logObject(page, "page") return page end function p.get_data(frame) page:init(frame) page = wikidata.get_links(page) -- mw.logObject(page, "page") make_list_projects_links() p.render_projects_links() make_list_encyclopedias_links() if page.is_author_page then -- рендеринг тега для отображения размещён в [[Модуль:Обавторе]] else p.renderEncyclopedias_aboutText() end page = require("Модуль:Источники по теме/Категоризация").get_categories(page) --mw.logObject(page.projects, "page.projects") return page end -- оформление меню со ссылками, как html в виде строки, для {{отексте}} и Модуль:Отексте function p.render_projects_links() local sources = page.projects -- mw.logObject(page.projects, "page.projects") local menu = '' if #sources > 0 then for i, w in ipairs(sources) do local links = {} local prefix = '<li class="submenu-label">' .. w.label .. '<ul>' local suffix = '</ul></li>' if #sources == 1 then prefix, suffix = '', '' end for _, v in pairs(w.links) do local project, link, lang, title = v.project, v.link, v.lang, v.title local is_recursive_link = page.title == title and lang == RU and project.project == WIKISOURCE if link and not is_recursive_link then local b = ""; if project.project == "wikidata" then b = "'''" end local prj_title = ''; if page.isPRS then prj_title = project.titlePRS else prj_title = project.title end local lang_label = ''; if lang and lang ~= RU then lang_label = " <sup><small>(" .. lang .. ")</small></sup>" end table.insert(links, '<li id="menu-wiki-'..project.project..'"><span class="about-extlink">' .. b .. "[[Файл:" .. project.logo .. "|13px|link=]] [[" .. link .. "|" .. prj_title .. "]]" .. b .. lang_label .. '</span></li>') end end if #links > 0 then menu = menu .. prefix .. table.concat(links, '\n') .. suffix end end end -- mw.logObject(menu, "menu") if is(menu) then menu = '<li id="menu-wiki">' .. "'''Википроекты'''<ul>" .. menu .. '</ul></li>' end page.projects_links_rendered = menu return menu end -- оформление меню со ссылками, как html в виде строки, для шапки {{отексте}}, вызывается из Модуль:Отексте function p.renderEncyclopedias_aboutText() local menu = '' local wikilinks = page.enc_wikilinks if #wikilinks > 0 then local _links = {}; for _, v in pairs(wikilinks) do table.insert(_links, "<li>" .. v .. "</li>") end local links = table.concat(_links, '\n') -- разделители local hr = "<hr style='width:100%%'>" local pre = "<div class=flexsep style='display:flex;justify-content:center;align-items:center;user-select:none'>" .. hr .. "<span style='font-size:smaller;padding:0 5px'>" local post = "</span>" .. hr .. "</div>" local otherlang, external = pre .. "на других языках" .. post, pre .. "внешние ссылки" .. post links = links:gsub( "(<li>%[%[:)", "<li class=lisep>" .. otherlang .. "</li>\n%1", 1 ) links = links:gsub( "(<li>%[http)", "<li class=lisep>" .. external .. "</li>\n%1", 1 ) local desc; if page.isPRS then desc = 'Энциклопедіи' else desc = 'Энциклопедии' end menu = '<li id="menu-dicts">' .. "'''" .. desc .. "'''<ul>" .. links .. '</ul></li>' end page.enc_links_rendered = menu -- mw.logObject(menu,"menu") return menu end -- проверка переменной, возврат её или nil если пустая function is(var) if (var == '' or var == nil) then return nil else return var end end return p