Wikizvor bswikisource https://bs.wikisource.org/wiki/Po%C4%8Detna_strana MediaWiki 1.47.0-wmf.14 first-letter Mediji Posebno Razgovor Korisnik Razgovor s korisnikom Wikizvor Razgovor o o Wikizvor Datoteka Razgovor o datoteci MediaWiki Razgovor o MediaWikiju Šablon Razgovor o šablonu Pomoć Razgovor o pomoći Kategorija Razgovor o kategoriji Page Page talk Index Index talk TimedText TimedText talk Modul Razgovor o modulu Event Event talk Modul:Header 828 5524 12147 12115 2026-08-11T11:48:53Z Vratiosevalter 3520 12147 Scribunto text/plain require('strict') local p = {} local getArgsRaw = require('Modul:Arguments').getArgs local yesno = require('Modul:Yesno') local headerAttribution = require('Modul:Header/attribution') local headerLang = require('Modul:Header/lang') local constructDefaultsort = require('Modul:Header/sort').construct_defaultsort local constructYear = require('Modul:Header/year').construct_year local constructHeader = require('Modul:Header structure').construct_header local plainSister = require('Modul:Plain sister')._plain_sister local parentLinks = require('Modul:Auto_parents')._parent_links local TRANSLATION_NS_ID = 114 -- placeholder, vidi otvoreno pitanje 2 ------------------------------------------------------------------------ -- Bosanski aliasi parametara (Faza 1 odluka #4). NAPOMENA: namjerno NE -- koristimo Modul:Arguments options.translate mehanizam — taj -- mehanizam je jednosmjerno preusmjeravanje ključa (moje_ime → sirovi -- ključ), pa ne može istovremeno podržati i "author=" i "autor=" kao -- validne ulaze. Umjesto toga, ručno spajamo frame.args + parent.args -- PRIJE poziva getArgs, razrješavajući bosanske alias ključeve u -- engleske. Ako korisnik da OBA (npr. i autor= i author=), engleski -- ima prednost — sprječava tihi konflikt (zahtjev zadatka, tačka 5.4). ------------------------------------------------------------------------ local ALIAS_BASE = { autor = 'author', prevodilac = 'translator', urednik = 'editor', kompozitor = 'composer', ilustrator = 'illustrator', saradnik = 'contributor', naslov = 'title', odjeljak = 'section', godina = 'year', napomene = 'notes', prethodno = 'previous', sljedece = 'next', precica = 'shortcut', korice = 'cover', jezik = 'language', izvornik = 'original', } -- Vraća engleski (kanonski) ključ za dati sirovi ključ. Podržava -- modifikatorske/numerisane varijante (autor2, autor-display, -- autor2-nolink...) prepoznavanjem alfabetskog prefiksa. local function canonical_key(k) if type(k) ~= 'string' then return k end if ALIAS_BASE[k] then return ALIAS_BASE[k] end local base, rest = k:match('^(%a+)(.-)$') if base and ALIAS_BASE[base] then return ALIAS_BASE[base] .. rest end return k end local function copy_translated(merged, t) if not t then return end -- Prvi prolaz: direktni (već engleski/kanonski) ključevi imaju prednost. for k, v in pairs(t) do if canonical_key(k) == k then merged[k] = v end end -- Drugi prolaz: bosanski aliasi, samo ako kanonski ključ još nije postavljen. for k, v in pairs(t) do local ck = canonical_key(k) if ck ~= k and merged[ck] == nil then merged[ck] = v end end end -- Sakuplja frame.args i parent.args (standardno ponašanje -- Modul:Arguments bez wrappers opcije), razrješava bosanske alias -- ključeve, vraća plain tabelu spremnu za getArgs. local function collect_and_translate(frame) local merged = {} copy_translated(merged, frame.args) local parent = frame.getParent and frame:getParent() copy_translated(merged, parent and parent.args) return merged end -- getArgs wrapper koji prosljeđuje već pripremljenu (alias-razriješenu) -- plain tabelu — Modul:Arguments je i dalje odgovoran za trim/blank -- obradu, memoizaciju, itd. local function getArgs(frame) return getArgsRaw(collect_and_translate(frame)) end ------------------------------------------------------------------------ -- Pomoćne funkcije za kategorizaciju ------------------------------------------------------------------------ local function has_numeric_args(args) for k in pairs(args) do if type(k) == 'number' then return true end end return false end local function has_explicit_formatting(args) for _, key in ipairs({ 'title', 'section' }) do local v = args[key] if v and (v:match("''") or v:match('<%s*/?%s*[iIbB][^>]*>')) then return true end end return false end local function add_cats(target, cats) for _, c in ipairs(cats or {}) do table.insert(target, c) end end -- Gradi prikazni red "Label: vrijednost" za jednu attribution ulogu. local function display_role(attribution, key) local entry = attribution.text[key] if not entry then return nil end return entry.label .. ': ' .. entry.value end ------------------------------------------------------------------------ -- Zajednička logika za header i translation_header ------------------------------------------------------------------------ local function build(args, is_translation) local testing = yesno(args.testing) local nocat = yesno(args.nocat) local categories = {} local title = mw.title.getCurrentTitle() local frame = mw.getCurrentFrame() -- Attribution (autor, prevodilac, urednik, kompozitor, ilustrator, saradnik) local attribution = headerAttribution.construct_attribution(args, is_translation) add_cats(categories, attribution.categories) -- Jezik (samo translation_header) local language_text, lang_cats = headerLang.construct_language_info(args, is_translation) add_cats(categories, lang_cats) -- Godina local year_text, year_cats = constructYear(args) add_cats(categories, year_cats) -- DefaultSort (uvijek se primjenjuje; wikitext fragment se dodaje na kraju) local defaultsort_wikitext, sort_cats = constructDefaultsort(args) add_cats(categories, sort_cats) -- Roditeljski linkovi (podstranice) — samo ako je stranica podstranica. local parent_links_text if title.text:find('/', 1, true) then local ok, result = pcall(parentLinks, { existing_links = 'yes' }) if ok then parent_links_text = result end end -- Sestrinski linkovi (Plain sister, Wikidata-bazirano) local sister_args = {} for _, key in ipairs({ 'wikipedia', 'commons', 'commonscat', 'wikiquote', 'wikinews', 'wiktionary', 'wikibooks', 'wikiversity', 'wikivoyage', 'portal', 'related-author', 'edition', 'textinfo', 'wikidataswitch', }) do if args[key] then sister_args[key] = args[key] end end local ok_sister, sister_output = pcall(plainSister, sister_args) if not ok_sister then sister_output = nil end -- Prečica if args.shortcut then if title:inNamespaces(0) then table.insert(categories, 'Stranice glavnog prostora sa prečicama') elseif title:inNamespaces(TRANSLATION_NS_ID) then table.insert(categories, 'Stranice prostora prijevoda sa prečicama') end end -- Korice za izvoz if args.cover then table.insert(categories, 'Stranice sa koricama za izvoz') end -- Eksplicitno formatiranje (osim ako je izričito dozvoljeno) if has_explicit_formatting(args) and not yesno(args['allow-explicit-formatting']) then table.insert(categories, 'Stranice s eksplicitnim formatiranjem u poljima zaglavlja') end -- Numerički argumenti if has_numeric_args(args) then table.insert(categories, 'Zaglavlja s numeričkim argumentima') end -- Parametar 'categories' (ručno dodane kategorije) if args.categories and args.categories ~= '' then table.insert(categories, 'Djela koja koriste parametar kategorija') for cat in mw.text.gsplit(args.categories, ',') do table.insert(categories, mw.text.trim(cat)) end end -- Sastavi podatke za Modul:Header structure local data = { title = args.title and frame:preprocess(args.title) or nil, attribution = { author = display_role(attribution, 'author'), translator = display_role(attribution, 'translator'), editor = display_role(attribution, 'editor'), composer = display_role(attribution, 'composer'), illustrator = display_role(attribution, 'illustrator'), contributor = display_role(attribution, 'contributor'), }, section = args.section, year_text = year_text and ('Godina: ' .. year_text) or nil, language_text = language_text, notes = args.notes, previous = args.previous and frame:preprocess(args.previous) or nil, next = args.next and frame:preprocess(args.next) or nil, parent_links = parent_links_text, sister_output = sister_output, is_translation = is_translation, } local header_html = constructHeader(data) if testing or nocat then -- Testing i nocat: prikaz bez kategorija (izbjegava zagađivanje -- pravih kategorija testnim/probnim stranicama). return header_html end local cat_html = '' for _, cat in ipairs(categories) do cat_html = cat_html .. '[[Kategorija:' .. cat .. ']]' end return header_html .. defaultsort_wikitext .. cat_html end ------------------------------------------------------------------------ -- Obavezne ulazne tačke (zahtjev zadatka, tačka 1) ------------------------------------------------------------------------ function p._header(args, argsWithBlanks) -- argsWithBlanks: vidi otvoreno pitanje 1 na vrhu fajla. return build(args, false) end function p.header(frame) local args = getArgs(frame) return p._header(args, args) end function p._translation_header(args, argsWithBlanks) args['language-required'] = true return build(args, true) end function p.translation_header(frame) local args = getArgs(frame) return p._translation_header(args, args) end return p gwkxski2tgc49swq9lw0dkrgltfn7rx Modul:Plain sister 828 5525 12145 12081 2026-08-11T11:46:29Z Vratiosevalter 3520 12145 Scribunto text/plain require('strict') local p = {} local yesno = require('Modul:Yesno') -- Projekti čiji sitelink čitamo direktno s Wikidata stavke. 'dbname' -- je standardni Wikimedia naziv baze projekta (koristi se u -- entity.sitelinks tabeli). local PROJECTS = { { key = 'wikipedia', dbname = 'bswiki', prefix = 'w', label = 'Wikipedija' }, { key = 'commons', dbname = 'commonswiki', prefix = 'c', label = 'Commons' }, { key = 'wikiquote', dbname = 'bswikiquote', prefix = 'q', label = 'Wikicitat' }, { key = 'wikinews', dbname = 'bswikinews', prefix = 'n', label = 'Wikivijesti' }, { key = 'wiktionary', dbname = 'bswiktionary', prefix = 'wikt', label = 'Wiktionary' }, { key = 'wikibooks', dbname = 'bswikibooks', prefix = 'b', label = 'Wikiknjige' }, { key = 'wikiversity', dbname = 'bswikiversity', prefix = 'v', label = 'Wikiverzitet' }, { key = 'wikivoyage', dbname = 'bswikivoyage', prefix = 'voy', label = 'Wikiputovanja' }, } -- Vraća Wikidata entitet za trenutnu stranicu, ili nil ako nije -- povezana ili Wikibase Client nije dostupan (vidi otvoreno pitanje). local function get_entity() if not mw.wikibase then return nil end local ok, entity = pcall(mw.wikibase.getEntityObject) if not ok or not entity then return nil end return entity end -- Gradi jedan sestrinski link; eksplicitni parametar ima prioritet -- nad Wikidata sitelinkom. local function build_link(args, entity, proj) local explicit = args[proj.key] if explicit and explicit ~= '' then return '[[' .. proj.prefix .. ':' .. explicit .. '|' .. proj.label .. ']]' end if entity and entity.sitelinks and entity.sitelinks[proj.dbname] then local title = entity.sitelinks[proj.dbname].title return '[[' .. proj.prefix .. ':' .. title .. '|' .. proj.label .. ']]' end return nil end -- Glavna funkcija. args može doći iz Modul:Header (direktan Lua poziv, -- kroz p._plain_sister) ili iz {{Plain sister}} šablona (p.plain_sister, -- preko getArgs). Vraća wikitext string ili nil ako nema šta prikazati. function p._plain_sister(args) local entity = get_entity() local links = {} for _, proj in ipairs(PROJECTS) do local link = build_link(args, entity, proj) if link then table.insert(links, link) end end -- Commons kategorija: posebna logika, prefiks 'Category:' po potrebi. local commonscat = args.commonscat if commonscat and commonscat ~= '' then local target = commonscat:match('^Category:') and commonscat or ('Category:' .. commonscat) table.insert(links, 1, '[[c:' .. target .. '|Commons kategorija]]') end if args.portal and args.portal ~= '' then table.insert(links, 1, '[[Portal:' .. args.portal .. '|portal]]') end if args['related-author'] and args['related-author'] ~= '' then -- Glavni prostor (Faza 1 odluka #1) — NE 'Autor:' prefiks. table.insert(links, 1, '[[' .. args['related-author'] .. '|srodni autor]]') end if yesno(args.edition) or args.textinfo then local talk = mw.title.getCurrentTitle().talkPageTitle if talk and talk.exists then table.insert(links, '[[' .. talk.fullText .. '|informacije o izdanju]]') end end -- Wikidata fallback pretraga, samo ako je eksplicitno tražena i -- stranica nema povezanu Wikidata stavku. if yesno(args.wikidataswitch) and not entity then local pagename = mw.title.getCurrentTitle().prefixedText table.insert(links, '[[d:Special:Search/' .. pagename .. '|Traži na Wikidati]]') end if #links == 0 then return nil end return 'Sestrinski projekti: ' .. table.concat(links, ', ') end function p.plain_sister(frame) local getArgs = require('Modul:Arguments').getArgs return p._plain_sister(getArgs(frame)) or '' end return p 32urervdxs4wr3uqwy5m983g2639zdt Šablon:Header/styles.css 10 5526 12144 12110 2026-08-11T11:44:53Z Vratiosevalter 3520 12144 sanitized-css text/css /* Šablon:Header/styles.css – poboljšana verzija */ .ws-header { display: block; margin-bottom: 1.2em; padding: 0.8em 1em; background: #f8f9fa; border: 1px solid #a2a9b1; border-radius: 6px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); } .ws-header .ws-header-title { font-size: 1.6em; font-weight: bold; color: #1a1a1a; line-height: 1.3; } .ws-header .ws-header-author, .ws-header .ws-header-translator, .ws-header .ws-header-year, .ws-header .ws-header-section { font-size: 0.95em; margin-top: 0.2em; color: #2c3e50; } .ws-header .ws-header-author { font-weight: 500; } .ws-header .ws-header-nav { font-size: 0.9em; margin-top: 0.4em; padding-top: 0.4em; border-top: 1px dashed #d0d7dd; color: #3366cc; } .ws-header .ws-header-nav span { margin: 0 0.4em; } .ws-header .ws-header-notes { font-size: 0.9em; margin-top: 0.4em; color: #54595d; font-style: italic; } .ws-header .ws-header-year { font-size: 0.9em; color: #666; } /* Responzivnost */ @media screen and (max-width: 640px) { .ws-header { padding: 0.5em 0.7em; } .ws-header .ws-header-title { font-size: 1.3em; } } .ws-header .ws-header-attribution { font-size: 0.95em; margin-top: 0.15em; color: #2c3e50; } .ws-header .ws-header-language { font-size: 0.9em; color: #666; margin-top: 0.15em; } .ws-header .ws-header-parents { font-size: 0.85em; color: #666; margin-bottom: 0.3em; } .ws-header .ws-header-sister { margin-top: 0.5em; padding-top: 0.3em; border-top: 1px solid #e0e4e8; font-size: 0.9em; color: #54595d; } .ws-header.ws-header--translation { border-left: 4px solid #2a4b7c; } lvwkzotfa0nrt272rfns6bkfz06f96t Šablon:Plain sister 10 5531 12146 12087 2026-08-11T11:47:43Z Vratiosevalter 3520 12146 wikitext text/x-wiki <includeonly>{{#invoke:Plain sister|plain_sister}}</includeonly><noinclude> {{Dokumentacija}}[[Kategorija:Šabloni]] </noinclude> 3q9or58m3oms2xkfvaehx53klgck2bb Modul:TableTools 828 5555 12137 2026-08-11T11:35:22Z Vratiosevalter 3520 Nova stranica: ------------------------------------------------------------------------------------ -- TableTools -- -- -- -- This module includes a number of functions for dealing with Lua tables. -- -- It is a meta-module, meant to be called from other Lua modules, and should not -- -- be called directly from #invoke.... 12137 Scribunto text/plain ------------------------------------------------------------------------------------ -- TableTools -- -- -- -- This module includes a number of functions for dealing with Lua tables. -- -- It is a meta-module, meant to be called from other Lua modules, and should not -- -- be called directly from #invoke. -- ------------------------------------------------------------------------------------ local libraryUtil = require('libraryUtil') local p = {} -- Define often-used variables and functions. local floor = math.floor local infinity = math.huge local checkType = libraryUtil.checkType local checkTypeMulti = libraryUtil.checkTypeMulti ------------------------------------------------------------------------------------ -- isPositiveInteger -- -- This function returns true if the given value is a positive integer, and false -- if not. Although it doesn't operate on tables, it is included here as it is -- useful for determining whether a given table key is in the array part or the -- hash part of a table. ------------------------------------------------------------------------------------ function p.isPositiveInteger(v) return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity end ------------------------------------------------------------------------------------ -- isNan -- -- This function returns true if the given number is a NaN value, and false if -- not. Although it doesn't operate on tables, it is included here as it is useful -- for determining whether a value can be a valid table key. Lua will generate an -- error if a NaN is used as a table key. ------------------------------------------------------------------------------------ function p.isNan(v) return type(v) == 'number' and v ~= v end ------------------------------------------------------------------------------------ -- shallowClone -- -- This returns a clone of a table. The value returned is a new table, but all -- subtables and functions are shared. Metamethods are respected, but the returned -- table will have no metatable of its own. ------------------------------------------------------------------------------------ function p.shallowClone(t) checkType('shallowClone', 1, t, 'table') local ret = {} for k, v in pairs(t) do ret[k] = v end return ret end ------------------------------------------------------------------------------------ -- removeDuplicates -- -- This removes duplicate values from an array. Non-positive-integer keys are -- ignored. The earliest value is kept, and all subsequent duplicate values are -- removed, but otherwise the array order is unchanged. ------------------------------------------------------------------------------------ function p.removeDuplicates(arr) checkType('removeDuplicates', 1, arr, 'table') local isNan = p.isNan local ret, exists = {}, {} for _, v in ipairs(arr) do if isNan(v) then -- NaNs can't be table keys, and they are also unique, so we don't need to check existence. ret[#ret + 1] = v elseif not exists[v] then ret[#ret + 1] = v exists[v] = true end end return ret end ------------------------------------------------------------------------------------ -- numKeys -- -- This takes a table and returns an array containing the numbers of any numerical -- keys that have non-nil values, sorted in numerical order. ------------------------------------------------------------------------------------ function p.numKeys(t) checkType('numKeys', 1, t, 'table') local isPositiveInteger = p.isPositiveInteger local nums = {} for k in pairs(t) do if isPositiveInteger(k) then nums[#nums + 1] = k end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- affixNums -- -- This takes a table and returns an array containing the numbers of keys with the -- specified prefix and suffix. For example, for the table -- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return -- {1, 3, 6}. ------------------------------------------------------------------------------------ function p.affixNums(t, prefix, suffix) checkType('affixNums', 1, t, 'table') checkType('affixNums', 2, prefix, 'string', true) checkType('affixNums', 3, suffix, 'string', true) local function cleanPattern(s) -- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally. return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1') end prefix = prefix or '' suffix = suffix or '' prefix = cleanPattern(prefix) suffix = cleanPattern(suffix) local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' local nums = {} for k in pairs(t) do if type(k) == 'string' then local num = mw.ustring.match(k, pattern) if num then nums[#nums + 1] = tonumber(num) end end end table.sort(nums) return nums end ------------------------------------------------------------------------------------ -- numData -- -- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table -- of subtables in the format -- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}. -- Keys that don't end with an integer are stored in a subtable named "other". The -- compress option compresses the table so that it can be iterated over with -- ipairs. ------------------------------------------------------------------------------------ function p.numData(t, compress) checkType('numData', 1, t, 'table') checkType('numData', 2, compress, 'boolean', true) local ret = {} for k, v in pairs(t) do local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$') if num then num = tonumber(num) local subtable = ret[num] or {} if prefix == '' then -- Positional parameters match the blank string; put them at the start of the subtable instead. prefix = 1 end subtable[prefix] = v ret[num] = subtable else local subtable = ret.other or {} subtable[k] = v ret.other = subtable end end if compress then local other = ret.other ret = p.compressSparseArray(ret) ret.other = other end return ret end ------------------------------------------------------------------------------------ -- compressSparseArray -- -- This takes an array with one or more nil values, and removes the nil values -- while preserving the order, so that the array can be safely traversed with -- ipairs. ------------------------------------------------------------------------------------ function p.compressSparseArray(t) checkType('compressSparseArray', 1, t, 'table') local ret = {} local nums = p.numKeys(t) for _, num in ipairs(nums) do ret[#ret + 1] = t[num] end return ret end ------------------------------------------------------------------------------------ -- sparseIpairs -- -- This is an iterator for sparse arrays. It can be used like ipairs, but can -- handle nil values. ------------------------------------------------------------------------------------ function p.sparseIpairs(t) checkType('sparseIpairs', 1, t, 'table') local nums = p.numKeys(t) local i = 0 local lim = #nums return function () i = i + 1 if i <= lim then local key = nums[i] return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- size -- -- This returns the size of a key/value pair table. It will also work on arrays, -- but for arrays it is more efficient to use the # operator. ------------------------------------------------------------------------------------ function p.size(t) checkType('size', 1, t, 'table') local i = 0 for _ in pairs(t) do i = i + 1 end return i end local function defaultKeySort(item1, item2) -- "number" < "string", so numbers will be sorted before strings. local type1, type2 = type(item1), type(item2) if type1 ~= type2 then return type1 < type2 elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then return tostring(item1) < tostring(item2) else return item1 < item2 end end ------------------------------------------------------------------------------------ -- keysToList -- -- Returns an array of the keys in a table, sorted using either a default -- comparison function or a custom keySort function. ------------------------------------------------------------------------------------ function p.keysToList(t, keySort, checked) if not checked then checkType('keysToList', 1, t, 'table') checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'}) end local arr = {} local index = 1 for k in pairs(t) do arr[index] = k index = index + 1 end if keySort ~= false then keySort = type(keySort) == 'function' and keySort or defaultKeySort table.sort(arr, keySort) end return arr end ------------------------------------------------------------------------------------ -- sortedPairs -- -- Iterates through a table, with the keys sorted using the keysToList function. -- If there are only numerical keys, sparseIpairs is probably more efficient. ------------------------------------------------------------------------------------ function p.sortedPairs(t, keySort) checkType('sortedPairs', 1, t, 'table') checkType('sortedPairs', 2, keySort, 'function', true) local arr = p.keysToList(t, keySort, true) local i = 0 return function () i = i + 1 local key = arr[i] if key ~= nil then return key, t[key] else return nil, nil end end end ------------------------------------------------------------------------------------ -- isArray -- -- Returns true if the given value is a table and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArray(v) if type(v) ~= 'table' then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- isArrayLike -- -- Returns true if the given value is iterable and all keys are consecutive -- integers starting at 1. ------------------------------------------------------------------------------------ function p.isArrayLike(v) if not pcall(pairs, v) then return false end local i = 0 for _ in pairs(v) do i = i + 1 if v[i] == nil then return false end end return true end ------------------------------------------------------------------------------------ -- invert -- -- Transposes the keys and values in an array. For example, {"a", "b", "c"} -> -- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to -- the index of the last duplicate) and NaN values are ignored. ------------------------------------------------------------------------------------ function p.invert(arr) checkType("invert", 1, arr, "table") local isNan = p.isNan local map = {} for i, v in ipairs(arr) do if not isNan(v) then map[v] = i end end return map end ------------------------------------------------------------------------------------ -- listToSet -- -- Creates a set from the array part of the table. Indexing the set by any of the -- values of the array returns true. For example, {"a", "b", "c"} -> -- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them -- never equal to any value (including other NaNs or even themselves). ------------------------------------------------------------------------------------ function p.listToSet(arr) checkType("listToSet", 1, arr, "table") local isNan = p.isNan local set = {} for _, v in ipairs(arr) do if not isNan(v) then set[v] = true end end return set end ------------------------------------------------------------------------------------ -- deepCopy -- -- Recursive deep copy function. Preserves identities of subtables. ------------------------------------------------------------------------------------ local function _deepCopy(orig, includeMetatable, already_seen) if type(orig) ~= "table" then return orig end -- already_seen stores copies of tables indexed by the original table. local copy = already_seen[orig] if copy ~= nil then return copy end copy = {} already_seen[orig] = copy -- memoize before any recursion, to avoid infinite loops for orig_key, orig_value in pairs(orig) do copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen) end if includeMetatable then local mt = getmetatable(orig) if mt ~= nil then setmetatable(copy, _deepCopy(mt, true, already_seen)) end end return copy end function p.deepCopy(orig, noMetatable, already_seen) checkType("deepCopy", 3, already_seen, "table", true) return _deepCopy(orig, not noMetatable, already_seen or {}) end ------------------------------------------------------------------------------------ -- sparseConcat -- -- Concatenates all values in the table that are indexed by a number, in order. -- sparseConcat{a, nil, c, d} => "acd" -- sparseConcat{nil, b, c, d} => "bcd" ------------------------------------------------------------------------------------ function p.sparseConcat(t, sep, i, j) local arr = {} local arr_i = 0 for _, v in p.sparseIpairs(t) do arr_i = arr_i + 1 arr[arr_i] = v end return table.concat(arr, sep, i, j) end ------------------------------------------------------------------------------------ -- length -- -- Finds the length of an array, or of a quasi-array with keys such as "data1", -- "data2", etc., using an exponential search algorithm. It is similar to the -- operator #, but may return a different value when there are gaps in the array -- portion of the table. Intended to be used on data loaded with mw.loadData. For -- other tables, use #. -- Note: #frame.args in frame object always be set to 0, regardless of the number -- of unnamed template parameters, so use this function for frame.args. ------------------------------------------------------------------------------------ function p.length(t, prefix) -- requiring module inline so that [[Modul:Exponential search]] which is -- only needed by this one function doesn't get millions of transclusions. -- NAPOMENA: naziv prilagođen na "Modul:" — postojanje ovog modula na -- bs.wikisource NIJE provjereno (vidi napomenu na vrhu fajla). local expSearch = require("Modul:Exponential search") checkType('length', 1, t, 'table') checkType('length', 2, prefix, 'string', true) return expSearch(function (i) local key if prefix then key = prefix .. tostring(i) else key = i end return t[key] ~= nil end) or 0 end ------------------------------------------------------------------------------------ -- inArray -- -- Returns true if searchElement is a member of the array, and false otherwise. -- Equivalent to JavaScript array.includes(searchElement) or -- array.includes(searchElement, fromIndex), except fromIndex is 1 indexed ------------------------------------------------------------------------------------ function p.inArray(array, searchElement, fromIndex) checkType("inArray", 1, array, "table") -- if searchElement is nil, error? fromIndex = tonumber(fromIndex) if fromIndex then if (fromIndex < 0) then fromIndex = #array + fromIndex + 1 end if fromIndex < 1 then fromIndex = 1 end for _, v in ipairs({unpack(array, fromIndex)}) do if v == searchElement then return true end end else for _, v in pairs(array) do if v == searchElement then return true end end end return false end ------------------------------------------------------------------------------------ -- merge -- -- Given the arrays, returns an array containing the elements of each input array -- in sequence. ------------------------------------------------------------------------------------ function p.merge(...) local arrays = {...} local ret = {} for i, arr in ipairs(arrays) do checkType('merge', i, arr, 'table') for _, v in ipairs(arr) do ret[#ret + 1] = v end end return ret end ------------------------------------------------------------------------------------ -- extend -- -- Extends the first array in place by appending all elements from the second -- array. ------------------------------------------------------------------------------------ function p.extend(arr1, arr2) checkType('extend', 1, arr1, 'table') checkType('extend', 2, arr2, 'table') for _, v in ipairs(arr2) do arr1[#arr1 + 1] = v end end return p pmpvokyfrk0smi4afgghl2nj0fdacmw Modul:Auto parents 828 5556 12138 2026-08-11T11:36:27Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} --p stands for package local getArgs = require('Modul:Arguments').getArgs local yesno = require('Modul:Yesno') --[=[ Return a formatted list of links referring to the parents of the current page Parameters: * page: the page title to use, if not the current page name * display: an override display title to use for the top level. * no_links: if yes, do not link page titles * existing_links: if yes, check whether pages exist before making them... 12138 Scribunto text/plain require('strict') local p = {} --p stands for package local getArgs = require('Modul:Arguments').getArgs local yesno = require('Modul:Yesno') --[=[ Return a formatted list of links referring to the parents of the current page Parameters: * page: the page title to use, if not the current page name * display: an override display title to use for the top level. * no_links: if yes, do not link page titles * existing_links: if yes, check whether pages exist before making them links Example: * page = A/B/C/D => [[A|A]], [[A/B|B]], [[A/B/C|C]] * page = A/B/C, display=Foo => [[A|Foo]], [[A/B|B]] ]=] function p._parent_links(args) args = args or {} local no_links = yesno(args.no_links or args['no links']) or false local existing_links = yesno(args.existing_links or args['existing links']) or false -- select override page name if given local title if args['page'] then title = mw.title.new(args['page']) else title = mw.title.getCurrentTitle() end local title_text = title.prefixedText -- the parts of the page title local parts = mw.text.split(title_text, '/', true) -- collected links for each parent -- at the top level, substitute the work display name if needed -- don't include namespace in link name local links = { args['display'] or title.rootText } if not no_links and (not existing_links or (existing_links and mw.title.new(parts[1]).exists)) then links[1] = '[[' .. parts[1] .. '|' .. links[1] .. ']]' end -- count forwards from the second-highest level to the second-lowest -- (the lowest level is the current page, not a parent) for level = 2, #parts - 1, 1 do local link_name = parts[level] local link_target = table.concat(parts, '/', 1, level) -- construct the link wikitext local link if no_links then link = link_name elseif existing_links then if mw.title.new(link_target).exists then link = '[[' .. link_target .. '|' .. link_name .. ']]' else link = link_name end else link = '[[' .. link_target .. '|' .. link_name .. ']]' end table.insert(links, link) end return table.concat(links, ', ') end function p.parent_links(frame) return p._parent_links(getArgs(frame)) end return p ac3qrlrr5y7gjyycy0na5bkbv4o6nsa Modul:Header/attribution 828 5557 12139 2026-08-11T11:38:43Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} local yesno = require('Modul:Yesno') -- Uloge koje modul podržava. `overrideLabel` je bosanski instrumental -- padež za tekst kategorije "Stranice s ručno navedenim X". local ROLES = { { key = 'author', label = 'Autor', overrideLabel = 'autorom', checkExistence = true }, { key = 'translator', label = 'Prevodilac', overrideLabel = 'prevodiocem', checkExistence = true }, -- vidi napomenu 2 { key = 'editor', label = '... 12139 Scribunto text/plain require('strict') local p = {} local yesno = require('Modul:Yesno') -- Uloge koje modul podržava. `overrideLabel` je bosanski instrumental -- padež za tekst kategorije "Stranice s ručno navedenim X". local ROLES = { { key = 'author', label = 'Autor', overrideLabel = 'autorom', checkExistence = true }, { key = 'translator', label = 'Prevodilac', overrideLabel = 'prevodiocem', checkExistence = true }, -- vidi napomenu 2 { key = 'editor', label = 'Urednik', overrideLabel = 'urednikom', checkExistence = false }, { key = 'composer', label = 'Kompozitor', overrideLabel = 'kompozitorom', checkExistence = true }, { key = 'illustrator', label = 'Ilustrator', overrideLabel = 'ilustratorom', checkExistence = true }, { key = 'contributor', label = 'Saradnik', overrideLabel = 'saradnikom', checkExistence = false }, } local EXISTENCE_CATEGORY = { author = 'Djela s nepostojećim stranicama autora', translator = 'Djela s nepostojećim stranicama prevodioca', composer = 'Djela s nepostojećim stranicama kompozitora', illustrator = 'Djela s nepostojećim stranicama ilustratora', } -- Provjerava postoji li stranica u GLAVNOM prostoru (namespace 0) za -- dato ime. Vraća true/false; nil ako ime nije dato. local function main_ns_page_exists(name) if not name or name == '' then return nil end local ok, title = pcall(mw.title.new, name, 0) if not ok or not title then return nil end return title.exists end -- Gradi link ili plain tekst za jedno ime, poštujući -display i -nolink. local function build_person_link(name, display, nolink) if not name or name == '' then return nil end if yesno(nolink) then return display or name end return '[[' .. name .. '|' .. (display or name) .. ']]' end -- Obrađuje jednu ulogu (npr. 'author'), uključujući numerisane -- varijante (author2, author3, ...). Vraća: text (wikitext ili nil), -- categories (lista imena, bez prefiksa "Kategorija:"), any_present (bool). function p.process_role(args, role, is_translation) local categories = {} -- Override ima prioritet nad normalnim linkovanjem/provjerom. local override = args['override-' .. role.key] if override and override ~= '' then table.insert(categories, 'Stranice s ručno navedenim ' .. role.overrideLabel) return override, categories, true end local list = {} local any_present = false local unknown = false local i = 1 while true do local suffix = (i == 1) and '' or tostring(i) local key = role.key .. suffix local name = args[key] -- section-author je alias za contributor u odjeljku (section), -- podržava samo neobrojanu varijantu. if i == 1 and role.key == 'contributor' and not name then name = args['section-author'] end if not name then break end any_present = true if name:lower() == 'unknown' then unknown = true else local display = args[key .. '-display'] local nolink = args[key .. '-nolink'] local link = build_person_link(name, display, nolink) if link then table.insert(list, link) end if role.checkExistence and not yesno(nolink) then local exists = main_ns_page_exists(name) if exists == false then table.insert(categories, EXISTENCE_CATEGORY[role.key]) end end end i = i + 1 end if role.key == 'contributor' and any_present then table.insert(categories, 'Stranice sa saradnikom') end if role.key == 'translator' then if any_present then table.insert(categories, 'Stranice s prevodiocem') elseif is_translation then table.insert(categories, 'Prijevodi bez podataka o prevodiocu') end end if role.key == 'editor' and unknown then table.insert(categories, 'Djela s nepoznatim urednicima') end if role.key == 'author' and unknown then table.insert(categories, is_translation and 'Prijevodi anonimnih djela' or 'Anonimni tekstovi') end local text if unknown then text = 'nepoznat' elseif #list > 0 then text = table.concat(list, ', ') end return text, categories, any_present end -- Glavna ulazna tačka. Vraća: -- { text = { author = {label=.., value=..}, ... }, categories = {...} } function p.construct_attribution(args, is_translation) local result = { text = {}, categories = {} } for _, role in ipairs(ROLES) do local text, cats = p.process_role(args, role, is_translation) if text then result.text[role.key] = { label = role.label, value = text } end for _, c in ipairs(cats) do table.insert(result.categories, c) end end return result end return p jdfef1tf8sn7cbwrfw5s8x2tu8rcnja Modul:Header/lang 828 5558 12140 2026-08-11T11:40:28Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} local yesno = require('Modul:Yesno') -- Mali ugrađeni rječnik ISO 639-1 → bosanski naziv jezika za najčešće -- slučajeve na bs.Wikisource. Vidi otvoreno pitanje 1 iznad. local LANGUAGE_NAMES = { bs = 'bosanski', hr = 'hrvatski', sr = 'srpski', en = 'engleski', de = 'njemački', fr = 'francuski', it = 'talijanski', tr = 'turski', ar = 'arapski', ru = 'ruski', es = 'španski', la = 'latinski', el = 'grčki', fa = 'perzijski', } -- V... 12140 Scribunto text/plain require('strict') local p = {} local yesno = require('Modul:Yesno') -- Mali ugrađeni rječnik ISO 639-1 → bosanski naziv jezika za najčešće -- slučajeve na bs.Wikisource. Vidi otvoreno pitanje 1 iznad. local LANGUAGE_NAMES = { bs = 'bosanski', hr = 'hrvatski', sr = 'srpski', en = 'engleski', de = 'njemački', fr = 'francuski', it = 'talijanski', tr = 'turski', ar = 'arapski', ru = 'ruski', es = 'španski', la = 'latinski', el = 'grčki', fa = 'perzijski', } -- Vraća prikazni bosanski naziv jezika za dati ISO kod, ili sam kod -- ako nije u rječniku (bolje nego prazan tekst). local function language_display_name(code) if not code or code == '' then return nil end return LANGUAGE_NAMES[code:lower()] or code end -- Vraća naziv kategorije "Djela izvorno na X" za dati ISO kod. function p.language_category_name(code) local name = language_display_name(code) if not name then return nil end return 'Djela izvorno na ' .. name end -- TODO: ID Translation namespace-a — placeholder dok Faza 1 odluka #2 -- ne bude realizovana (Phabricator zahtjev). Vidi otvoreno pitanje 4. local TRANSLATION_NS_ID = 114 -- Glavna funkcija: obrađuje 'language' i 'original' parametre za -- Translation header. Vraća (text, categories); text je nil za obični -- Header (is_translation = false). function p.construct_language_info(args, is_translation) local categories = {} if not is_translation then return nil, categories end table.insert(categories, 'Prijevodi') local text_parts = {} local code = args.language local nolanguagecat = yesno(args.nolanguagecat) if code and code ~= '' then local name = language_display_name(code) table.insert(text_parts, 'Izvorni jezik: ' .. name) if not nolanguagecat then local cat = p.language_category_name(code) if cat then table.insert(categories, cat) end end else table.insert(categories, 'Prijevodi bez izvornog jezika') end local original = args.original if original and original ~= '' then table.insert(text_parts, '[[' .. original .. '|izvornik]]') else table.insert(categories, 'Prijevodi bez izvornog izvora') end -- Translation-namespace-specifične kategorije (trenutno mrtav kod — -- vidi otvoreno pitanje 4). local title = mw.title.getCurrentTitle() if title:inNamespaces(TRANSLATION_NS_ID) then table.insert(categories, 'Wikizvor prijevodi') if code and code ~= '' then table.insert(categories, 'Wikizvor prijevodi djela na ' .. language_display_name(code)) end if not (original and original ~= '') then table.insert(categories, 'Wikizvor prijevodi bez izvornog izvora') end end local text = #text_parts > 0 and table.concat(text_parts, ' — ') or nil return text, categories end return p 8nhqmjnrh9ptz7t3f37phwjkgv4xlqj Modul:Header/sort 828 5559 12141 2026-08-11T11:41:12Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} -- Uklanja putanju podstranice (sve iza prve '/') iz naslova — sortiranje -- po punoj putanji sa kosim crtama daje loš redoslijed u kategorijama. local function strip_subpage(title_text) return title_text:match('^([^/]+)') or title_text end local function auto_sortkey(title) return strip_subpage(title.text) end -- Glavna funkcija. Vraća (wikitext_fragment, categories). -- wikitext_fragment sadrži {{DEFAULTSORT:...}} i dodaje se na kraj... 12141 Scribunto text/plain require('strict') local p = {} -- Uklanja putanju podstranice (sve iza prve '/') iz naslova — sortiranje -- po punoj putanji sa kosim crtama daje loš redoslijed u kategorijama. local function strip_subpage(title_text) return title_text:match('^([^/]+)') or title_text end local function auto_sortkey(title) return strip_subpage(title.text) end -- Glavna funkcija. Vraća (wikitext_fragment, categories). -- wikitext_fragment sadrži {{DEFAULTSORT:...}} i dodaje se na kraj -- izlaza Modul:Header. function p.construct_defaultsort(args) local categories = {} local title = mw.title.getCurrentTitle() local explicit = args.defaultsort or args.sortkey local sortkey local applied_explicit = false if explicit and explicit ~= '' then sortkey = explicit applied_explicit = true else sortkey = auto_sortkey(title) end if applied_explicit then table.insert(categories, 'Zaglavlja koja primjenjuju DefaultSort ključ') if sortkey == title.text then table.insert(categories, 'Zaglavlja sa DefaultSort jednakim naslovu stranice') end end local wikitext = '{{DEFAULTSORT:' .. sortkey .. '}}' return wikitext, categories end return p r1e8de2f6l1vxr3i8qzx1etmsd3xwvf Modul:Header/year 828 5560 12142 2026-08-11T11:42:20Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} local yesno = require('Modul:Yesno') -- Parsira uneseni 'year'. Vraća (display_text, category_year); -- category_year je broj (za kategorizaciju) ili nil ako se ne može -- svesti na jednu godinu. local function parse_year(raw) if not raw or raw == '' then return nil, nil end if raw == '?' then return 'nepoznata', nil end local circa = raw:match('^c/(%d+)$') if circa then return 'oko ' .. circa .. '.', tonumber(circa) end loc... 12142 Scribunto text/plain require('strict') local p = {} local yesno = require('Modul:Yesno') -- Parsira uneseni 'year'. Vraća (display_text, category_year); -- category_year je broj (za kategorizaciju) ili nil ako se ne može -- svesti na jednu godinu. local function parse_year(raw) if not raw or raw == '' then return nil, nil end if raw == '?' then return 'nepoznata', nil end local circa = raw:match('^c/(%d+)$') if circa then return 'oko ' .. circa .. '.', tonumber(circa) end local from, to = raw:match('^(%d+)/(%d+)$') if from and to then return from .. '/' .. to .. '.', tonumber(from) end local plain = raw:match('^(%d+)$') if plain then return plain .. '.', tonumber(plain) end -- Nestandardan oblik (npr. decenija/vijek — vidi otvoreno pitanje 1): -- prikaži kao dat, ne kategoriši po broju. return raw, nil end -- Glavna funkcija. Vraća (text, categories). function p.construct_year(args) local categories = {} local raw = args.year if not raw or raw == '' then return nil, categories end local display, cat_year = parse_year(raw) local noyear = yesno(args.noyear) local noyearcat = yesno(args.noyearcat) if noyear then table.insert(categories, 'Stranice sa noyear') end if noyearcat then table.insert(categories, 'Stranice sa noyearcat') end if cat_year and not noyearcat then table.insert(categories, 'Djela iz ' .. cat_year .. '. godine') end local text = (not noyear) and display or nil return text, categories end return p h5wx9bcu3nxqhqk279yc5k5tlbfpuwr Modul:Header structure 828 5561 12143 2026-08-11T11:43:40Z Vratiosevalter 3520 Nova stranica: require('strict') local p = {} -- Doda <div class="..."> u html objekat samo ako je content ne-prazan. local function add_div(html, class, content) if not content or content == '' then return end html:tag('div'):addClass(class):wikitext(content) end --[[ Glavna funkcija. Prima sastavljen 'data' objekat (priprema ga orkestrator Modul:Header iz izlaza ostalih podmodula) i vraća gotov wikitext string. data polja: title – preprocesovan wikitext naslova at... 12143 Scribunto text/plain require('strict') local p = {} -- Doda <div class="..."> u html objekat samo ako je content ne-prazan. local function add_div(html, class, content) if not content or content == '' then return end html:tag('div'):addClass(class):wikitext(content) end --[[ Glavna funkcija. Prima sastavljen 'data' objekat (priprema ga orkestrator Modul:Header iz izlaza ostalih podmodula) i vraća gotov wikitext string. data polja: title – preprocesovan wikitext naslova attribution – { author=, translator=, editor=, composer=, illustrator=, contributor= } (svaki već gotov wikitext red "Label: linkovi", ili nil) section – tekst sekcije/podnaslova year_text – prikazni tekst godine (iz Modul:Header/year) language_text – prikazni tekst jezika (iz Modul:Header/lang, samo za translation_header) notes – napomene previous, next – preprocesovan wikitext navigacije (polje "next" je sigurno kao naziv tabele, ne kosi se sa Lua ugrađenom funkcijom next()) parent_links – wikitext roditeljskih linkova (iz Modul:Auto_parents), opcionalno sister_output – wikitext sestrinskih linkova (iz Modul:Plain sister) is_translation – bool, dodaje ws-header--translation modifikator ]] function p.construct_header(data) local html = mw.html.create('div') html:addClass('ws-header') if data.is_translation then html:addClass('ws-header--translation') end if data.parent_links and data.parent_links ~= '' then html:tag('div'):addClass('ws-header-parents'):wikitext(data.parent_links) end add_div(html, 'ws-header-title', data.title) local attribution = data.attribution or {} add_div(html, 'ws-header-author', attribution.author) if data.is_translation then add_div(html, 'ws-header-translator', attribution.translator) end add_div(html, 'ws-header-attribution', attribution.editor) add_div(html, 'ws-header-attribution', attribution.composer) add_div(html, 'ws-header-attribution', attribution.illustrator) add_div(html, 'ws-header-attribution', attribution.contributor) add_div(html, 'ws-header-section', data.section) add_div(html, 'ws-header-language', data.language_text) add_div(html, 'ws-header-year', data.year_text) add_div(html, 'ws-header-notes', data.notes) if data.previous or data.next then local nav = html:tag('div'):addClass('ws-header-nav') if data.previous then nav:tag('span'):wikitext('← ' .. data.previous) end if data.next then nav:tag('span'):wikitext(data.next .. ' →') end end if data.sister_output and data.sister_output ~= '' then html:tag('div'):addClass('ws-header-sister'):wikitext(data.sister_output) end return tostring(html) end return p suwf1ckw6dhxdc3lu3o4tf1fojl2ewj