Wikipedia piwiki https://pi.wikipedia.org/wiki/%E0%A4%AA%E0%A4%AE%E0%A5%81%E0%A4%96_%E0%A4%AA%E0%A4%A4%E0%A5%8D%E0%A4%A4_Pamukha_patta MediaWiki 1.47.0-wmf.18 first-letter मीडिया विसेस सम्भासित अवयव अवयव सम्भासित Wikipedia Wikipedia सम्भासित पटिमा पटिमा सम्भासित मीडियाविकि मीडियाविकि सम्भासित पटिरूप पटिरूप सम्भासित अवस्सय अवस्सय सम्भासित विभाग विभाग सम्भासित TimedText TimedText talk Module Module talk Event Event talk पटिरूप:Namespace detect 10 5729 103785 101766 2026-09-04T05:52:30Z 咽頭べさ 6149 103785 wikitext text/x-wiki {{SAFESUBST:<noinclude />#invoke:Namespace detect|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> l3ti6zjxip68spdlt018btofjtao8um पटिरूप:Mbox 10 5975 103784 84486 2026-09-04T05:51:50Z 咽頭べさ 6149 103784 wikitext text/x-wiki {{#invoke:Message box|mbox}}<noinclude> {{documentation}} <!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> </noinclude> aqsrswx233se5jbjaza2b2hrk7pgx53 Module:TableTools 828 6489 103766 96445 2026-09-03T13:05:23Z Hamish 5487 Update from [[d:Special:GoToLinkedPage/enwiki/Q15408619|master]] using [[mw:Synchronizer| #Synchronizer]] 103766 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 [[Module:Exponential search]] which is -- only needed by this one function doesn't get millions of transclusions local expSearch = require("Module: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 4n03zk6kcoeg4gz82mieeh94c1szcjy Module:Exponential search 828 7351 103767 2026-09-03T22:01:51Z Hamish 5487 [IPE-NEXT] Quick edit imported from [[:w:en:Module:Exponential search]] 103767 Scribunto text/plain -- This module provides a generic exponential search algorithm. require[[strict]] local checkType = require('libraryUtil').checkType local floor = math.floor local function midPoint(lower, upper) return floor(lower + (upper - lower) / 2) end local function search(testFunc, i, lower, upper) if testFunc(i) then if i + 1 == upper then return i end lower = i if upper then i = midPoint(lower, upper) else i = i * 2 end return search(testFunc, i, lower, upper) else upper = i i = midPoint(lower, upper) return search(testFunc, i, lower, upper) end end return function (testFunc, init) checkType('Exponential search', 1, testFunc, 'function') checkType('Exponential search', 2, init, 'number', true) if init and (init < 1 or init ~= floor(init) or init == math.huge) then error(string.format( "invalid init value '%s' detected in argument #2 to " .. "'Exponential search' (init value must be a positive integer)", tostring(init) ), 2) end init = init or 2 if not testFunc(1) then return nil end return search(testFunc, init, 1, nil) end jqqi8l27tb73lglksbukg2g3bzt3fmv पटिरूप:Sandbox heading 10 7352 103768 2026-09-04T01:13:37Z 咽頭べさ 6149 Created page with "{{Ombox | image = [[File:Edit In Sandbox Icon - Color.svg|75px|alt=|link=]] | imageright = {{#ifeq:{{FULLPAGENAME}}|Wikipedia talk:Sandbox |{{Ombox/shortcut|WT:SB|WT:SAND|WT:SANDBOX|WT:TEST|WT:TESTING|WT:FOO|WT:FOOBAR}} | {{#ifeq:{{FULLPAGENAME}}|Wikipedia:Sandbox |{{Ombox/shortcut|WP:SB|WP:SAND|WP:SANDBOX|WP:TEST|WP:TESTING|WP:FOO|WP:FOOBAR}} }} }} | text = {{#ifeq:{{TALKPAGENAME}}|{{FULLPAGENAME}}|{{Sandbox heading/Ta..." 103768 wikitext text/x-wiki {{Ombox | image = [[File:Edit In Sandbox Icon - Color.svg|75px|alt=|link=]] | imageright = {{#ifeq:{{FULLPAGENAME}}|Wikipedia talk:Sandbox |{{Ombox/shortcut|WT:SB|WT:SAND|WT:SANDBOX|WT:TEST|WT:TESTING|WT:FOO|WT:FOOBAR}} | {{#ifeq:{{FULLPAGENAME}}|Wikipedia:Sandbox |{{Ombox/shortcut|WP:SB|WP:SAND|WP:SANDBOX|WP:TEST|WP:TESTING|WP:FOO|WP:FOOBAR}} }} }} | text = {{#ifeq:{{TALKPAGENAME}}|{{FULLPAGENAME}}|{{Sandbox heading/Talk}}}} पाळि वीकीपीःदीःयाः स्स सन्धबोक्ख Sandbox पिट्ठतो साधु आगमनं॥ सन्धबोक्ख पिट्ठानि नाम वीकीपीःदीःयाः पिट्ठानं सोधनकिरिया अनुभवं लभितुं परिक्खनट्ठानं होति॥<br/>इमं सन्धबोक्खं सोधेतुं <span class="plainlinks">'''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} इध]'''</span> वा इमस्स पिट्ठस्स उपरि "सोधेहि" तापिकं {{talk other|&nbsp;– वा नवसम्भासनं आरभितुकामो होति चे "नवविभागं लिखहि" }} एतं पीळेहि॥ सोधितकाले "'''{{int:Savearticle}}'''" एतं सोधितपिट्ठं रक्खतु खलुकं पीळेहि॥ सोधितानि पुब्बपिट्ठिं पस्सितुकामो होति चे "'''{{int:Showpreview}}'''" एतं पीळेत्वा पस्सितुं सक्कोति॥ {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|action=edit}}|मूलमूलं सोधेहि}} वा {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|veaction=edit}}|दिस्समानं सोधेहि}} इदं पिट्ठं नियमतो सोधियते॥ अञ्ञे अनुयुत्तापि इमस्मिं पिट्ठे सोधनपरिक्खं करोन्ति। तस्मा इध तया लिखितं सब्बं सदा '''तिट्ठति न होति'''॥[{{#switch:{{FULLPAGENAME}} |Draft:Sandbox |User:Sandbox |User talk:Sandbox |Wikipedia talk:Sandbox={{fullurl:{{FULLPAGENAME}}|action=edit&preload=Template%3ASandbox+reset}} |{{fullurl:Wikipedia:Sandbox|action=edit&oldid=544066}} }}सोधितं सन्धबोक्खं सोधेतुं इध पीळेहि]॥ त्वं पञ्जिकतो अनुयुत्तो होसि चे। पविसित्वा[{{fullurl:Special:Mypage/sandbox|action=edit&preload=Template:User_sandbox/preload}} अत्तनो सन्धबोक्खं इध निम्मातुं सक्कोति]॥ याचना: सन्धबोक्ख अन्तरे बाधकानि। विवादापन्नानि च वा Copyright सहितानि अत्थानि '''मा लिखहि'''॥ :''वीकीपीःदीःयाः उपरि सासनपण्णं लिखनत्थाय मूलसिक्खं [[en:Wikipedia:Contributing to Wikipedia|सासनपण्णं लिखनं]] इध पस्सितुं सक्कोति॥'' [[Category:वीकीपीःदीःयाः सोधनउपकारानि]] }}<!--(end Ombox) Auto-categorization:-->{{#switch:{{FULLPAGENAME}} |Wikipedia:Sandbox|Draft:Sandbox=[[Category:वीकीपीःदीःयाः सोधनउपकारानि]]}}<!-- --><noinclude> {{Documentation}} <!--Interwikis at [[d:q3938]]--> </noinclude> k39mv3f2laimkap12b351ntsexveqf9 103769 103768 2026-09-04T01:15:28Z 咽頭べさ 6149 103769 wikitext text/x-wiki {{Ombox | image = [[File:Edit In Sandbox Icon - Color.svg|75px|alt=|link=]] | imageright = {{#ifeq:{{FULLPAGENAME}}|Wikipedia talk:Sandbox |{{Ombox/shortcut|WT:SB|WT:SAND|WT:SANDBOX|WT:TEST|WT:TESTING|WT:FOO|WT:FOOBAR}} | {{#ifeq:{{FULLPAGENAME}}|Wikipedia:Sandbox |{{Ombox/shortcut|WP:SB|WP:SAND|WP:SANDBOX|WP:TEST|WP:TESTING|WP:FOO|WP:FOOBAR}} }} }} | text = {{#ifeq:{{TALKPAGENAME}}|{{FULLPAGENAME}}|{{Sandbox heading/Talk}}}} पाळि वीकीपीःदीःयाः स्स सन्धबोक्ख Sandbox पिट्ठतो साधु आगमनं॥ सन्धबोक्ख पिट्ठानि नाम वीकीपीःदीःयाः पिट्ठानं सोधनकिरिया अनुभवं लभितुं परिक्खनट्ठानं होति॥<br/>इमं सन्धबोक्खं सोधेतुं <span class="plainlinks">'''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} इध]'''</span> वा इमस्स पिट्ठस्स उपरि "सोधेहि" तापिकं {{talk other|&nbsp;– वा नवसम्भासनं आरभितुकामो होति चे "नवविभागं लिखहि" }} एतं पीळेहि॥ सोधितकाले "'''{{int:Savearticle}}'''" एतं सोधितपिट्ठं रक्खतु खलुकं पीळेहि॥ सोधितानि पुब्बपिट्ठिं पस्सितुकामो होति चे "'''{{int:Showpreview}}'''" एतं पीळेत्वा पस्सितुं सक्कोति॥ {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|action=edit}}|मूलमूलं सोधेहि}} वा {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|veaction=edit}}|दिस्समानं सोधेहि}} इदं पिट्ठं नियमतो सोधियते॥ अञ्ञे अनुयुत्तापि इमस्मिं पिट्ठे सोधनपरिक्खं करोन्ति। तस्मा इध तया लिखितं सब्बं सदा '''तिट्ठति न होति'''॥[{{#switch:{{FULLPAGENAME}} |Draft:Sandbox |User:Sandbox |User talk:Sandbox |Wikipedia talk:Sandbox={{fullurl:{{FULLPAGENAME}}|action=edit&preload=Template%3ASandbox+reset}} |{{fullurl:Wikipedia:Sandbox|action=edit&oldid=544066}} }}सोधितं सन्धबोक्खं सोधेतुं इध पीळेहि]॥ त्वं पञ्जिकतो अनुयुत्तो होसि चे। पविसित्वा[{{fullurl:Special:Mypage/sandbox|action=edit&preload=Template:User_sandbox/preload}} अत्तनो सन्धबोक्खं इध निम्मातुं सक्कोति]॥ याचना: सन्धबोक्ख अन्तरे बाधकानि। विवादापन्नानि च वा Copyright सहितानि अत्थानि '''मा लिखहि'''॥ :''वीकीपीःदीःयाः उपरि सासनपण्णं लिखनत्थाय मूलसिक्खं [[:en:Wikipedia:Contributing to Wikipedia|सासनपण्णं लिखनं]] इध पस्सितुं सक्कोति॥'' [[Category:वीकीपीःदीःयाः सोधनउपकारानि]] }}<!--(end Ombox) Auto-categorization:-->{{#switch:{{FULLPAGENAME}} |Wikipedia:Sandbox|Draft:Sandbox=[[Category:वीकीपीःदीःयाः सोधनउपकारानि]]}}<!-- --><noinclude> {{Documentation}} <!--Interwikis at [[d:q3938]]--> </noinclude> n5sg1wgixslps2sbu6w37uio6hd4abe 103797 103769 2026-09-04T10:59:53Z 咽頭べさ 6149 103797 wikitext text/x-wiki {{Ombox | image = [[File:Edit In Sandbox Icon - Color.svg|75px|alt=|link=]] | imageright = {{#ifeq:{{FULLPAGENAME}}|Wikipedia talk:Sandbox |{{Ombox/shortcut|WT:SB|WT:SAND|WT:SANDBOX|WT:TEST|WT:TESTING|WT:FOO|WT:FOOBAR}} | {{#ifeq:{{FULLPAGENAME}}|Wikipedia:Sandbox |{{Ombox/shortcut|WP:SB|WP:SAND|WP:SANDBOX|WP:TEST|WP:TESTING|WP:FOO|WP:FOOBAR}} }} }} | text = {{#ifeq:{{TALKPAGENAME}}|{{FULLPAGENAME}}|{{Sandbox heading/Talk}}}} पाळि वीकीपीःदीःयाः स्स सन्धबोक्ख Sandbox पिट्ठतो साधु आगमनं॥ सन्धबोक्ख पिट्ठानि नाम वीकीपीःदीःयाः पिट्ठानं सोधनकिरिया अनुभवं लभितुं परिक्खनट्ठानं होति॥<br/>इमं सन्धबोक्खं सोधेतुं <span class="plainlinks">'''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} इध]'''</span> वा इमस्स पिट्ठस्स उपरि "सोधेहि" तापिकं {{talk other|&nbsp;– वा नवसम्भासनं आरभितुकामो होति चे "नवविभागं लिखहि" }} एतं पीळेहि॥ सोधितकाले "'''{{int:Savearticle}}'''" एतं सोधितपिट्ठं रक्खतु खलुकं पीळेहि॥ सोधितानि पुब्बपिट्ठिं पस्सितुकामो होति चे "'''{{int:Showpreview}}'''" एतं पीळेत्वा पस्सितुं सक्कोति॥ {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|action=edit}}|मूलमूलं सोधेहि}} वा {{clickable button 2|url={{fullurl:{{FULLPAGENAME}}|veaction=edit}}|दिस्समानं सोधेहि}} इदं पिट्ठं नियमतो सोधियते॥ अञ्ञे अनुयुत्तापि इमस्मिं पिट्ठे सोधनपरिक्खं करोन्ति। तस्मा इध तया लिखितं सब्बं सदा '''तिट्ठति न होति'''॥[{{#switch:{{FULLPAGENAME}} |Draft:Sandbox |User:Sandbox |User talk:Sandbox |Wikipedia talk:Sandbox={{fullurl:{{FULLPAGENAME}}|action=edit&preload=Template%3ASandbox+reset}} |{{fullurl:Wikipedia:Sandbox|action=edit&oldid=544066}} }}सोधितं सन्धबोक्खं सोधेतुं इध पीळेहि]॥ त्वं पञ्जिकतो अनुयुत्तो होसि चे। पविसित्वा[{{fullurl:Special:Mypage/sandbox|action=edit&preload=Template:User_sandbox/preload}} अत्तनो सन्धबोक्खं इध निम्मातुं सक्कोति]॥ याचना: सन्धबोक्ख अन्तरे बाधकानि। विवादापन्नानि च वा Copyright सहितानि अत्थानि '''मा लिखहि'''॥ :''वीकीपीःदीःयाः उपरि सासनपण्णं लिखनत्थाय मूलसिक्खं [[:en:Wikipedia:Contributing to Wikipedia|सासनपण्णं लिखनं]] इध पस्सितुं सक्कोति॥'' [[Category:वीकीपीःदीःयाः सोधनउपकारानि]] }}<!--(end Ombox) Auto-categorization:-->{{#switch:{{FULLPAGENAME}} |Wikipedia:Sandbox|Draft:Sandbox=[[विभाग:विकिपीडिया सोधनउपकारानि ]]}}<!-- --><noinclude> {{Documentation}} <!--Interwikis at [[d:q3938]]--> </noinclude> qf450kgre7nadcnuqq14jvvm3dw33z7 पटिरूप:Not a sandbox 10 7353 103770 2026-09-04T01:22:44Z 咽頭べさ 6149 Created page with "{{Mbox | type = content | image = [[File:Sandbox Not.svg|50px|alt=|link=]] | text = '''इमं पिट्ठं सन्धिबाहिरं Sandbox ''<u>न होति</u>''॥ तस्मा परिक्खणकरणत्थं न आयुज्जितब्बं॥''' परिक्खितुं [[Wikipedia:Sandbox]] ठाने करोहि॥ }}<noinclude> {{Documentation}} </noinclude>" 103770 wikitext text/x-wiki {{Mbox | type = content | image = [[File:Sandbox Not.svg|50px|alt=|link=]] | text = '''इमं पिट्ठं सन्धिबाहिरं Sandbox ''<u>न होति</u>''॥ तस्मा परिक्खणकरणत्थं न आयुज्जितब्बं॥''' परिक्खितुं [[Wikipedia:Sandbox]] ठाने करोहि॥ }}<noinclude> {{Documentation}} </noinclude> ly9zsou2iui8r4bja0m5t6ai5kmr6v4 विभाग:विकिपीडिया सोधनउपकारानि 14 7354 103771 2026-09-04T01:24:33Z 咽頭べさ 6149 Created page with "[[Category:वीकीपीःदीःयाः सोधनं]]" 103771 wikitext text/x-wiki [[Category:वीकीपीःदीःयाः सोधनं]] b6cxw18yeu4yooe3gxwwuc0ehrnu4qy 103772 103771 2026-09-04T01:26:07Z 咽頭べさ 6149 103772 wikitext text/x-wiki {{pp-semi|small=yes}} {{polluted category}} {{Not a sandbox}} [[Category:वीकीपीःदीःयाः सोधनं]] 5sxs0g1lz9uh2rff8lmfwoscdjx6v4y 103787 103772 2026-09-04T07:20:36Z ङघिञ 8448 ङघिञ moved page [[विभाग:वीकीपीःदीःयाः सोधनउपकारानि]] to [[विभाग:विकिपीडिया सोधनउपकारानि]]: Misspelled title 103772 wikitext text/x-wiki {{pp-semi|small=yes}} {{polluted category}} {{Not a sandbox}} [[Category:वीकीपीःदीःयाः सोधनं]] 5sxs0g1lz9uh2rff8lmfwoscdjx6v4y पटिरूप:Protected page 10 7355 103773 2026-09-04T01:27:41Z 咽頭べさ 6149 Created page with "<includeonly>{{#invoke:Protected page|main}}</includeonly><noinclude> {{Documentation}} </noinclude>" 103773 wikitext text/x-wiki <includeonly>{{#invoke:Protected page|main}}</includeonly><noinclude> {{Documentation}} </noinclude> 6y1fepgg5duiitvvcck1nbt4hrqzfwb 103774 103773 2026-09-04T01:28:01Z 咽頭べさ 6149 咽頭べさ moved page [[पटिरूप:Pp-semi]] to [[पटिरूप:Protected page]] 103773 wikitext text/x-wiki <includeonly>{{#invoke:Protected page|main}}</includeonly><noinclude> {{Documentation}} </noinclude> 6y1fepgg5duiitvvcck1nbt4hrqzfwb पटिरूप:Pp-semi 10 7356 103775 2026-09-04T01:28:01Z 咽頭べさ 6149 咽頭べさ moved page [[पटिरूप:Pp-semi]] to [[पटिरूप:Protected page]] 103775 wikitext text/x-wiki #REDIRECT [[पटिरूप:Protected page]] 7qg2wgziukt5bgs5wag254vjk0825lo पटिरूप:Polluted category 10 7357 103776 2026-09-04T01:28:59Z 咽頭べさ 6149 Created page with "<nowiki /><noinclude>{{Documentation}}<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE, THANKS --></noinclude>" 103776 wikitext text/x-wiki <nowiki /><noinclude>{{Documentation}}<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE, THANKS --></noinclude> 4onaw4seacscd08nxwsxjqt517qhu3d पटिरूप:Cmbox 10 7358 103777 2026-09-04T01:30:29Z 咽頭べさ 6149 Created page with "{{#invoke:Message box|cmbox}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude>" 103777 wikitext text/x-wiki {{#invoke:Message box|cmbox}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> 2wg1g94nws2nefrz0o1pxm105lovzoz पटिरूप:Maintenance category 10 7359 103778 2026-09-04T02:10:49Z 咽頭べさ 6149 Created page with "{{Cmbox | type = notice | text = इमं वग्गो '''परिपालन [[:en:Help:Category|वग्गो]] (administration category)''' होति। अनागते पाळि वीकी पबुद्धिं गच्छन्ते अंग्रे वीकीपीःदीःयाःयं ठितं :en:Wikipedia:Categorization#Non-article and maintenance categories|वीकीपीःदीःयाः परिपालन..." 103778 wikitext text/x-wiki {{Cmbox | type = notice | text = इमं वग्गो '''परिपालन [[:en:Help:Category|वग्गो]] (administration category)''' होति। अनागते पाळि वीकी पबुद्धिं गच्छन्ते अंग्रे वीकीपीःदीःयाःयं ठितं [[:en:Wikipedia:Categorization#Non-article and maintenance categories|वीकीपीःदीःयाः परिपालन प्रोजेक्ट]] रूपेन पयुञ्जितुं होति॥ इमं वग्गो महाविगन्थस्स अवयवो न होति॥ इमस्मिं वग्गे [[:en:Wikipedia:What is an article?|लेखनं]] न होन्तानि पिट्ठानि सन्निपतितानि होन्ति। लेखनस्स वत्थुविसयअनुसारेन न होत्वा लेखनस्स परिपूरणता/अपरिपूरणतादि-अवत्थानुसारेन सम्बुद्धं होति॥ इमं वग्गं लेखनस्स वत्थुविसय वग्ग (content category) अन्तरे न पक्खिपेहि॥ {{#if:{{Yesno|{{{container|}}}}}|<p>इमं वग्गो सयमेव वग्गेन वग्गितं कतानं '''[[:Category:वग्गुपवग्गसमूहो|वग्गुपवग्गसमूहो (container category)]]''' एकं होति॥ तस्मा इमस्मिं वग्गे '''[[WP:SUBCAT|उपवग्गं (sub category)]]''' मत्तमेव पक्खिपेहि॥ {{#ifeq:{{{container_category|}}}|no||{{Category other|{{{category|[[Category:वग्गुपवग्गसमूहो]]}}}}}}}}}{{#if:{{Yesno|{{{hidden|}}}}}|__HIDDENCAT__<p>इमं वग्गो '''[[:Category:गूळ्हवग्गो|गूळ्हवग्गो (hidden category)]]''' एकं होति॥ सामञेन इमं वग्गन्तोगधलेखनेसु न दिस्सति॥ दिस्सतुकामो यदि होति। पुब्बपसन्नतो (Preferences) अन्तरे ठितं 'अधिकरणपसन्नतो' सीसकस्स अधो [[:Special:Preferences#mw-prefsection-rendering|'गूळ्हवग्गे दस्सेतुं']] सद्दं चिनोहि॥}}{{#if:{{Yesno|{{{tracking|}}}}}|<p>इमं '''[[:Category:अनुगमनवग्गो|अनुगमनवग्गो]]''' एकं होति। सम्बन्धितानुसारेन सुसण्ठितानि पिट्ठानि अनुगम्म महाचारं निम्माति॥ पिट्ठानि अनुगमनवग्गेसु पटिरूप हि द्वारेन पक्खिपितानि होन्ति॥{{#if:{{{description|}}}|<p>{{{description}}}}}{{#ifeq:{{{tracking_category|}}}|no||{{Category other|{{{category|[[Category:अनुगमनवग्गानि]]}}}}}}}}} | imageright = {{#if:{{{shortcut|{{{shortcut1|}}}}}}|{{Shortcut|{{{shortcut|{{{shortcut1|}}}}}}|{{{shortcut2|}}}|{{{shortcut3|}}}|{{{shortcut4|}}}|{{{shortcut5|}}}}}}} }}<includeonly>{{#ifeq: {{lc:{{{nocat|false}}}}}|false|{{Single namespace|category}}{{#if:{{{1|}}}|<p><div style="text-align: left;">{{{ALTTEXT|'''विवरणं''':}}} {{{1|}}}</div>}}|<!-- Category suppressed -->}}</includeonly><noinclude> {{Documentation}} <!-- Please add categories to the /doc sub-page, not here. --> [[Category:वग्ग नाममण्डल पटिरूप तानि]] [[Category:अनुगमन पटिरूप तानि]] </noinclude> 6e3qbnp8ywugaing25crt3q3ortgazs पटिरूप:Category other 10 7360 103779 2026-09-04T02:12:56Z 咽頭べさ 6149 Created page with "{{safesubst:<noinclude/>#switch: <noinclude><!-- If no or empty "demospace" parameter then detect namespace --></noinclude> {{safesubst:<noinclude/>#if:{{{demospace|}}} | {{safesubst:<noinclude/>lc: {{{demospace}}} }} <noinclude><!-- Use lower case "demospace" --></noinclude> | {{safesubst:<noinclude/>#ifeq:{{safesubst:<noinclude/>NAMESPACE}}|{{safesubst:<noinclude/>ns:Category}} | category | other }} }} | category = {{{1|}}} | other | #default =..." 103779 wikitext text/x-wiki {{safesubst:<noinclude/>#switch: <noinclude><!-- If no or empty "demospace" parameter then detect namespace --></noinclude> {{safesubst:<noinclude/>#if:{{{demospace|}}} | {{safesubst:<noinclude/>lc: {{{demospace}}} }} <noinclude><!-- Use lower case "demospace" --></noinclude> | {{safesubst:<noinclude/>#ifeq:{{safesubst:<noinclude/>NAMESPACE}}|{{safesubst:<noinclude/>ns:Category}} | category | other }} }} | category = {{{1|}}} | other | #default = {{{2|}}} }}<noinclude><!-- End switch --> {{documentation}} <!-- Add categories and interwikis to the /doc subpage, not here! --> </noinclude> t67v4qbh02ab0u9w0tb11xsliusi23k Module:Protected page 828 7361 103780 2026-09-04T02:23:24Z 咽頭べさ 6149 Created page with "-- This module implements {{pp-meta}} and its daughter templates such as -- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}. -- Initialise necessary modules. require('strict') local makeFileLink = require('Module:File link')._main local effectiveProtectionLevel = require('Module:Effective protection level')._main local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main local yesno = require('Module:Yesno') -- Lazily initialise modules and..." 103780 Scribunto text/plain -- This module implements {{pp-meta}} and its daughter templates such as -- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}. -- Initialise necessary modules. require('strict') local makeFileLink = require('Module:File link')._main local effectiveProtectionLevel = require('Module:Effective protection level')._main local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main local yesno = require('Module:Yesno') -- Lazily initialise modules and objects we don't always need. local getArgs, makeMessageBox, lang -- Set constants. local CONFIG_MODULE = 'Module:Protected page/config' -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function makeCategoryLink(cat, sort) if cat then return string.format( '[[%s:%s|%s]]', mw.site.namespaces[14].name, cat, sort ) end end -- Validation function for the expiry and the protection date local function validateDate(dateString, dateType) if not lang then lang = mw.language.getContentLanguage() end local success, result = pcall(lang.formatDate, lang, 'U', dateString) if success then result = tonumber(result) if result then return result end end error(string.format( 'invalid %s: %s', dateType, tostring(dateString) ), 4) end local function makeFullUrl(page, query, display) return string.format( '[%s %s]', tostring(mw.uri.fullUrl(page, query)), display ) end -- Given a directed graph formatted as node -> table of direct successors, -- get a table of all nodes reachable from a given node (though always -- including the given node). local function getReachableNodes(graph, start) local toWalk, retval = {[start] = true}, {} while true do -- Can't use pairs() since we're adding and removing things as we're iterating local k = next(toWalk) -- This always gets the "first" key if k == nil then return retval end toWalk[k] = nil retval[k] = true for _,v in ipairs(graph[k]) do if not retval[v] then toWalk[v] = true end end end end -------------------------------------------------------------------------------- -- Protection class -------------------------------------------------------------------------------- local Protection = {} Protection.__index = Protection Protection.supportedActions = { edit = true, move = true, autoreview = true, upload = true } Protection.bannerConfigFields = { 'text', 'explanation', 'tooltip', 'alt', 'link', 'image' } function Protection.new(args, cfg, title) local obj = {} obj._cfg = cfg obj.title = title or mw.title.getCurrentTitle() -- Set action if not args.action then obj.action = 'edit' elseif Protection.supportedActions[args.action] then obj.action = args.action else error(string.format( 'invalid action: %s', tostring(args.action) ), 3) end -- Set level obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title) if not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then -- Users need to be autoconfirmed to move pages anyway, so treat -- semi-move-protected pages as unprotected. obj.level = '*' end -- Set expiry local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title) if effectiveExpiry == 'infinity' then obj.expiry = 'indef' elseif effectiveExpiry ~= 'unknown' then obj.expiry = validateDate(effectiveExpiry, 'expiry date') end -- Set reason if args[1] then obj.reason = mw.ustring.lower(args[1]) if obj.reason:find('|') then error('reasons cannot contain the pipe character ("|")', 3) end end -- Set protection date if args.date then obj.protectionDate = validateDate(args.date, 'protection date') end -- Set banner config do obj.bannerConfig = {} local configTables = {} if cfg.banners[obj.action] then configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason] end if cfg.defaultBanners[obj.action] then configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level] configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default end configTables[#configTables + 1] = cfg.masterBanner for i, field in ipairs(Protection.bannerConfigFields) do for j, t in ipairs(configTables) do if t[field] then obj.bannerConfig[field] = t[field] break end end end end return setmetatable(obj, Protection) end function Protection:isUserScript() -- Whether the page is a user JavaScript or CSS page. local title = self.title return title.namespace == 2 and ( title.contentModel == 'javascript' or title.contentModel == 'css' ) end function Protection:isProtected() return self.level ~= '*' end function Protection:shouldShowLock() -- Whether we should output a banner/padlock return self:isProtected() and not self:isUserScript() end -- Whether this page needs a protection category. Protection.shouldHaveProtectionCategory = Protection.shouldShowLock function Protection:isTemporary() return type(self.expiry) == 'number' end function Protection:makeProtectionCategory() if not self:shouldHaveProtectionCategory() then return '' end local cfg = self._cfg local title = self.title -- Get the expiry key fragment. local expiryFragment if self.expiry == 'indef' then expiryFragment = self.expiry elseif type(self.expiry) == 'number' then expiryFragment = 'temp' end -- Get the namespace key fragment. local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace] if not namespaceFragment and title.namespace % 2 == 1 then namespaceFragment = 'talk' end -- Define the order that key fragments are tested in. This is done with an -- array of tables containing the value to be tested, along with its -- position in the cfg.protectionCategories table. local order = { {val = expiryFragment, keypos = 1}, {val = namespaceFragment, keypos = 2}, {val = self.reason, keypos = 3}, {val = self.level, keypos = 4}, {val = self.action, keypos = 5} } --[[ -- The old protection templates used an ad-hoc protection category system, -- with some templates prioritising namespaces in their categories, and -- others prioritising the protection reason. To emulate this in this module -- we use the config table cfg.reasonsWithNamespacePriority to set the -- reasons for which namespaces have priority over protection reason. -- If we are dealing with one of those reasons, move the namespace table to -- the end of the order table, i.e. give it highest priority. If not, the -- reason should have highest priority, so move that to the end of the table -- instead. --]] table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3)) --[[ -- Define the attempt order. Inactive subtables (subtables with nil "value" -- fields) are moved to the end, where they will later be given the key -- "all". This is to cut down on the number of table lookups in -- cfg.protectionCategories, which grows exponentially with the number of -- non-nil keys. We keep track of the number of active subtables with the -- noActive parameter. --]] local noActive, attemptOrder do local active, inactive = {}, {} for i, t in ipairs(order) do if t.val then active[#active + 1] = t else inactive[#inactive + 1] = t end end noActive = #active attemptOrder = active for i, t in ipairs(inactive) do attemptOrder[#attemptOrder + 1] = t end end --[[ -- Check increasingly generic key combinations until we find a match. If a -- specific category exists for the combination of key fragments we are -- given, that match will be found first. If not, we keep trying different -- key fragment combinations until we match using the key -- "all-all-all-all-all". -- -- To generate the keys, we index the key subtables using a binary matrix -- with indexes i and j. j is only calculated up to the number of active -- subtables. For example, if there were three active subtables, the matrix -- would look like this, with 0 corresponding to the key fragment "all", and -- 1 corresponding to other key fragments. -- -- j 1 2 3 -- i -- 1 1 1 1 -- 2 0 1 1 -- 3 1 0 1 -- 4 0 0 1 -- 5 1 1 0 -- 6 0 1 0 -- 7 1 0 0 -- 8 0 0 0 -- -- Values of j higher than the number of active subtables are set -- to the string "all". -- -- A key for cfg.protectionCategories is constructed for each value of i. -- The position of the value in the key is determined by the keypos field in -- each subtable. --]] local cats = cfg.protectionCategories for i = 1, 2^noActive do local key = {} for j, t in ipairs(attemptOrder) do if j > noActive then key[t.keypos] = 'all' else local quotient = i / 2 ^ (j - 1) quotient = math.ceil(quotient) if quotient % 2 == 1 then key[t.keypos] = t.val else key[t.keypos] = 'all' end end end key = table.concat(key, '|') local attempt = cats[key] if attempt then return makeCategoryLink(attempt, title.text) end end return '' end function Protection:isIncorrect() if not self:shouldHaveProtectionCategory() then return true end if type(self.expiry) ~= 'number' then return false end local expiry = os.date('*t', self.expiry) -- Avoid checking today.day or os.time(), unless close. https://phabricator.wikimedia.org/T416616 local today = os.date('*t') return (expiry.year < today.year) or (expiry.year == today.year and expiry.month < today.month) or (expiry.year == today.year and expiry.month == today.month and expiry.day < today.day) or (expiry.year == today.year and expiry.month == today.month and expiry.day == today.day and self.expiry < os.time()) end function Protection:isTemplateProtectedNonTemplate() local action, namespace = self.action, self.title.namespace return self.level == 'templateeditor' and ( (action ~= 'edit' and action ~= 'move') or (namespace ~= 10 and namespace ~= 828) ) end function Protection:makeCategoryLinks() local msg = self._cfg.msg local ret = {self:makeProtectionCategory()} if self:isIncorrect() then ret[#ret + 1] = makeCategoryLink( msg['tracking-category-incorrect'], self.title.text ) end if self:isTemplateProtectedNonTemplate() then ret[#ret + 1] = makeCategoryLink( msg['tracking-category-template'], self.title.text ) end return table.concat(ret) end -------------------------------------------------------------------------------- -- Blurb class -------------------------------------------------------------------------------- local Blurb = {} Blurb.__index = Blurb Blurb.bannerTextFields = { text = true, explanation = true, tooltip = true, alt = true, link = true } function Blurb.new(protectionObj, args, cfg) return setmetatable({ _cfg = cfg, _protectionObj = protectionObj, _args = args }, Blurb) end -- Private methods -- function Blurb:_formatDate(num) -- Formats a Unix timestamp into dd Month, YYYY format. lang = lang or mw.language.getContentLanguage() local success, date = pcall( lang.formatDate, lang, self._cfg.msg['expiry-date-format'] or 'j F Y', '@' .. tostring(num) ) if success then return date end end function Blurb:_getExpandedMessage(msgKey) return self:_substituteParameters(self._cfg.msg[msgKey]) end function Blurb:_substituteParameters(msg) if not self._params then local parameterFuncs = {} parameterFuncs.CURRENTVERSION = self._makeCurrentVersionParameter parameterFuncs.EDITREQUEST = self._makeEditRequestParameter parameterFuncs.EXPIRY = self._makeExpiryParameter parameterFuncs.EXPLANATIONBLURB = self._makeExplanationBlurbParameter parameterFuncs.IMAGELINK = self._makeImageLinkParameter parameterFuncs.INTROBLURB = self._makeIntroBlurbParameter parameterFuncs.INTROFRAGMENT = self._makeIntroFragmentParameter parameterFuncs.PAGETYPE = self._makePagetypeParameter parameterFuncs.PROTECTIONBLURB = self._makeProtectionBlurbParameter parameterFuncs.PROTECTIONDATE = self._makeProtectionDateParameter parameterFuncs.PROTECTIONLEVEL = self._makeProtectionLevelParameter parameterFuncs.PROTECTIONLOG = self._makeProtectionLogParameter parameterFuncs.TALKPAGE = self._makeTalkPageParameter parameterFuncs.TOOLTIPBLURB = self._makeTooltipBlurbParameter parameterFuncs.TOOLTIPFRAGMENT = self._makeTooltipFragmentParameter parameterFuncs.VANDAL = self._makeVandalTemplateParameter self._params = setmetatable({}, { __index = function (t, k) local param if parameterFuncs[k] then param = parameterFuncs[k](self) end param = param or '' t[k] = param return param end }) end msg = msg:gsub('${(%u+)}', self._params) return msg end function Blurb:_makeCurrentVersionParameter() -- A link to the page history or the move log, depending on the kind of -- protection. local pagename = self._protectionObj.title.prefixedText if self._protectionObj.action == 'move' then -- We need the move log link. return makeFullUrl( 'Special:Log', {type = 'move', page = pagename}, self:_getExpandedMessage('current-version-move-display') ) else -- We need the history link. return makeFullUrl( pagename, {action = 'history'}, self:_getExpandedMessage('current-version-edit-display') ) end end function Blurb:_makeEditRequestParameter() local mEditRequest = require('Module:Submit an edit request') local action = self._protectionObj.action local level = self._protectionObj.level -- Get the edit request type. local requestType if action == 'edit' then if level == 'autoconfirmed' then requestType = 'semi' elseif level == 'extendedconfirmed' then requestType = 'extended' elseif level == 'templateeditor' then requestType = 'template' end end requestType = requestType or 'full' -- Get the display value. local display = self:_getExpandedMessage('edit-request-display') return mEditRequest._link{type = requestType, display = display} end function Blurb:_makeExpiryParameter() local expiry = self._protectionObj.expiry if type(expiry) == 'number' then return self:_formatDate(expiry) else return expiry end end function Blurb:_makeExplanationBlurbParameter() -- Cover special cases first. if self._protectionObj.title.namespace == 8 then -- MediaWiki namespace return self:_getExpandedMessage('explanation-blurb-nounprotect') end -- Get explanation blurb table keys local action = self._protectionObj.action local level = self._protectionObj.level local talkKey = self._protectionObj.title.isTalkPage and 'talk' or 'subject' -- Find the message in the explanation blurb table and substitute any -- parameters. local explanations = self._cfg.explanationBlurbs local msg if explanations[action][level] and explanations[action][level][talkKey] then msg = explanations[action][level][talkKey] elseif explanations[action][level] and explanations[action][level].default then msg = explanations[action][level].default elseif explanations[action].default and explanations[action].default[talkKey] then msg = explanations[action].default[talkKey] elseif explanations[action].default and explanations[action].default.default then msg = explanations[action].default.default else error(string.format( 'could not find explanation blurb for action "%s", level "%s" and talk key "%s"', action, level, talkKey ), 8) end return self:_substituteParameters(msg) end function Blurb:_makeImageLinkParameter() local imageLinks = self._cfg.imageLinks local action = self._protectionObj.action local level = self._protectionObj.level local msg if imageLinks[action][level] then msg = imageLinks[action][level] elseif imageLinks[action].default then msg = imageLinks[action].default else msg = imageLinks.edit.default end return self:_substituteParameters(msg) end function Blurb:_makeIntroBlurbParameter() if self._protectionObj:isTemporary() then return self:_getExpandedMessage('intro-blurb-expiry') else return self:_getExpandedMessage('intro-blurb-noexpiry') end end function Blurb:_makeIntroFragmentParameter() if self._protectionObj:isTemporary() then return self:_getExpandedMessage('intro-fragment-expiry') else return self:_getExpandedMessage('intro-fragment-noexpiry') end end function Blurb:_makePagetypeParameter() local pagetypes = self._cfg.pagetypes return pagetypes[self._protectionObj.title.namespace] or pagetypes.default or error('no default pagetype defined', 8) end function Blurb:_makeProtectionBlurbParameter() local protectionBlurbs = self._cfg.protectionBlurbs local action = self._protectionObj.action local level = self._protectionObj.level local msg if protectionBlurbs[action][level] then msg = protectionBlurbs[action][level] elseif protectionBlurbs[action].default then msg = protectionBlurbs[action].default elseif protectionBlurbs.edit.default then msg = protectionBlurbs.edit.default else error('no protection blurb defined for protectionBlurbs.edit.default', 8) end return self:_substituteParameters(msg) end function Blurb:_makeProtectionDateParameter() local protectionDate = self._protectionObj.protectionDate if type(protectionDate) == 'number' then return self:_formatDate(protectionDate) else return protectionDate end end function Blurb:_makeProtectionLevelParameter() local protectionLevels = self._cfg.protectionLevels local action = self._protectionObj.action local level = self._protectionObj.level local msg if protectionLevels[action][level] then msg = protectionLevels[action][level] elseif protectionLevels[action].default then msg = protectionLevels[action].default elseif protectionLevels.edit.default then msg = protectionLevels.edit.default else error('no protection level defined for protectionLevels.edit.default', 8) end return self:_substituteParameters(msg) end function Blurb:_makeProtectionLogParameter() local pagename = self._protectionObj.title.prefixedText if self._protectionObj.action == 'autoreview' then -- We need the pending changes log. return makeFullUrl( 'Special:Log', {type = 'stable', page = pagename}, self:_getExpandedMessage('pc-log-display') ) else -- We need the protection log. return makeFullUrl( 'Special:Log', {type = 'protect', page = pagename}, self:_getExpandedMessage('protection-log-display') ) end end function Blurb:_makeTalkPageParameter() return string.format( '[[%s:%s#%s|%s]]', mw.site.namespaces[self._protectionObj.title.namespace].talk.name, self._protectionObj.title.text, self._args.section or 'top', self:_getExpandedMessage('talk-page-link-display') ) end function Blurb:_makeTooltipBlurbParameter() if self._protectionObj:isTemporary() then return self:_getExpandedMessage('tooltip-blurb-expiry') else return self:_getExpandedMessage('tooltip-blurb-noexpiry') end end function Blurb:_makeTooltipFragmentParameter() if self._protectionObj:isTemporary() then return self:_getExpandedMessage('tooltip-fragment-expiry') else return self:_getExpandedMessage('tooltip-fragment-noexpiry') end end function Blurb:_makeVandalTemplateParameter() return mw.getCurrentFrame():expandTemplate{ title="vandal-m", args={self._args.user or self._protectionObj.title.baseText} } end -- Public methods -- function Blurb:makeBannerText(key) -- Validate input. if not key or not Blurb.bannerTextFields[key] then error(string.format( '"%s" is not a valid banner config field', tostring(key) ), 2) end -- Generate the text. local msg = self._protectionObj.bannerConfig[key] if type(msg) == 'string' then return self:_substituteParameters(msg) elseif type(msg) == 'function' then msg = msg(self._protectionObj, self._args) if type(msg) ~= 'string' then error(string.format( 'bad output from banner config function with key "%s"' .. ' (expected string, got %s)', tostring(key), type(msg) ), 4) end return self:_substituteParameters(msg) end end -------------------------------------------------------------------------------- -- BannerTemplate class -------------------------------------------------------------------------------- local BannerTemplate = {} BannerTemplate.__index = BannerTemplate function BannerTemplate.new(protectionObj, cfg) local obj = {} obj._cfg = cfg -- Set the image filename. local imageFilename = protectionObj.bannerConfig.image if imageFilename then obj._imageFilename = imageFilename else -- If an image filename isn't specified explicitly in the banner config, -- generate it from the protection status and the namespace. local action = protectionObj.action local level = protectionObj.level local namespace = protectionObj.title.namespace local reason = protectionObj.reason -- Deal with special cases first. if ( namespace == 10 or namespace == 828 or reason and obj._cfg.indefImageReasons[reason] ) and action == 'edit' and level == 'sysop' and not protectionObj:isTemporary() then -- Fully protected modules and templates get the special red "indef" -- padlock. obj._imageFilename = obj._cfg.msg['image-filename-indef'] else -- Deal with regular protection types. local images = obj._cfg.images if images[action] then if images[action][level] then obj._imageFilename = images[action][level] elseif images[action].default then obj._imageFilename = images[action].default end end end end return setmetatable(obj, BannerTemplate) end function BannerTemplate:renderImage() local filename = self._imageFilename or self._cfg.msg['image-filename-default'] or 'Transparent.gif' return makeFileLink{ file = filename, size = (self.imageWidth or 20) .. 'px', alt = self._imageAlt, link = self._imageLink, caption = self.imageCaption } end -------------------------------------------------------------------------------- -- Banner class -------------------------------------------------------------------------------- local Banner = setmetatable({}, BannerTemplate) Banner.__index = Banner function Banner.new(protectionObj, blurbObj, cfg) local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb. obj.imageWidth = 40 obj.imageCaption = blurbObj:makeBannerText('alt') -- Large banners use the alt text for the tooltip. obj._reasonText = blurbObj:makeBannerText('text') obj._explanationText = blurbObj:makeBannerText('explanation') obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing. return setmetatable(obj, Banner) end function Banner:__tostring() -- Renders the banner. makeMessageBox = makeMessageBox or require('Module:Message box').main local reasonText = self._reasonText or error('no reason text set', 2) local explanationText = self._explanationText local mbargs = { page = self._page, type = 'protection', image = self:renderImage(), text = string.format( "'''%s'''%s", reasonText, explanationText and '<br />' .. explanationText or '' ) } return makeMessageBox('mbox', mbargs) end -------------------------------------------------------------------------------- -- Padlock class -------------------------------------------------------------------------------- local Padlock = setmetatable({}, BannerTemplate) Padlock.__index = Padlock function Padlock.new(protectionObj, blurbObj, cfg) local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb. obj.imageWidth = 20 obj.imageCaption = blurbObj:makeBannerText('tooltip') obj._imageAlt = blurbObj:makeBannerText('alt') obj._imageLink = blurbObj:makeBannerText('link') obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action] or cfg.padlockIndicatorNames.default or 'pp-default' return setmetatable(obj, Padlock) end function Padlock:__tostring() local frame = mw.getCurrentFrame() -- The nowiki tag helps prevent whitespace at the top of articles. return frame:extensionTag{name = 'nowiki'} .. frame:extensionTag{ name = 'indicator', args = {name = self._indicatorName}, content = self:renderImage() } end -------------------------------------------------------------------------------- -- Exports -------------------------------------------------------------------------------- local p = {} function p._exportClasses() -- This is used for testing purposes. return { Protection = Protection, Blurb = Blurb, BannerTemplate = BannerTemplate, Banner = Banner, Padlock = Padlock, } end function p._main(args, cfg, title) args = args or {} cfg = cfg or require(CONFIG_MODULE) local protectionObj = Protection.new(args, cfg, title) local ret = {} -- If a page's edit protection is equally or more restrictive than its -- protection from some other action, then don't bother displaying anything -- for the other action (except categories). if not yesno(args.catonly) and (protectionObj.action == 'edit' or args.demolevel or not getReachableNodes( cfg.hierarchy, protectionObj.level )[effectiveProtectionLevel('edit', protectionObj.title)]) then -- Initialise the blurb object local blurbObj = Blurb.new(protectionObj, args, cfg) -- Render the banner if protectionObj:shouldShowLock() then ret[#ret + 1] = tostring( (yesno(args.small) and Padlock or Banner) .new(protectionObj, blurbObj, cfg) ) end end -- Render the categories if yesno(args.category) ~= false then ret[#ret + 1] = protectionObj:makeCategoryLinks() end -- For arbitration enforcement, flagging [[WP:PIA]] pages to enable [[Special:AbuseFilter/1339]] to flag edits to them if protectionObj.level == "extendedconfirmed" then if require("Module:TableTools").inArray(protectionObj.title.talkPageTitle.categories, "Wikipedia pages subject to the extended confirmed restriction related to the Arab-Israeli conflict") then ret[#ret + 1] = "<p class='PIA-flag' style='display:none; visibility:hidden;' title='This page is subject to the extended confirmed restriction related to the Arab-Israeli conflict.'></p>" end end return table.concat(ret) end function p.main(frame, cfg) cfg = cfg or require(CONFIG_MODULE) -- Find default args, if any. local parent = frame.getParent and frame:getParent() local defaultArgs = parent and cfg.wrappers[parent:getTitle():gsub('/sandbox$', '')] -- Find user args, and use the parent frame if we are being called from a -- wrapper template. getArgs = getArgs or require('Module:Arguments').getArgs local userArgs = getArgs(frame, { parentOnly = defaultArgs, frameOnly = not defaultArgs }) -- Build the args table. User-specified args overwrite default args. local args = {} for k, v in pairs(defaultArgs or {}) do args[k] = v end for k, v in pairs(userArgs) do args[k] = v end return p._main(args, cfg) end return p p8ryzquso3eyufqyguwh2oyqz5eu1l6 Module:Protected page/config 828 7362 103781 2026-09-04T05:45:04Z 咽頭べさ 6149 Created page with "-- This module provides configuration data for [[Module:Protection banner]]. return { -------------------------------------------------------------------------------- -- -- BANNER DATA -- -------------------------------------------------------------------------------- --[[ -- Banner data consists of six fields: -- * text - the main protection text that appears at the top of protection -- banners. -- * explanation - the text that appear..." 103781 Scribunto text/plain -- This module provides configuration data for [[Module:Protection banner]]. return { -------------------------------------------------------------------------------- -- -- BANNER DATA -- -------------------------------------------------------------------------------- --[[ -- Banner data consists of six fields: -- * text - the main protection text that appears at the top of protection -- banners. -- * explanation - the text that appears below the main protection text, used -- to explain the details of the protection. -- * tooltip - the tooltip text you see when you move the mouse over a small -- padlock icon. -- * link - the page that the small padlock icon links to. -- * alt - the alt text for the small padlock icon. This is also used as tooltip -- text for the large protection banners. -- * image - the padlock image used in both protection banners and small padlock -- icons. -- -- The module checks in three separate tables to find a value for each field. -- First it checks the banners table, which has values specific to the reason -- for the page being protected. Then the module checks the defaultBanners -- table, which has values specific to each protection level. Finally, the -- module checks the masterBanner table, which holds data for protection -- templates to use if no data has been found in the previous two tables. -- -- The values in the banner data can take parameters. These are specified -- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name -- enclosed in curly braces). -- -- Available parameters: -- -- ${CURRENTVERSION} - a link to the page history or the move log, with the -- display message "current-version-edit-display" or -- "current-version-move-display". -- -- ${EDITREQUEST} - a link to create an edit request for the current page. -- -- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes -- on the talk page; you may submit a request to ask an administrator to make -- an edit if it is minor or supported by consensus." -- -- ${IMAGELINK} - a link to set the image to, depending on the protection -- action and protection level. -- -- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry -- is set. E.g. "Editing of this page by new or unregistered users is currently -- disabled until dd Month YYYY." -- -- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation -- so that it can be used in run-on sentences. -- -- ${PAGETYPE} - the type of the page, e.g. "article" or "template". -- Defined in the cfg.pagetypes table. -- -- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g. -- "Editing of this page by new or unregistered users is currently disabled" -- -- ${PROTECTIONDATE} - the protection date, if it has been supplied to the -- template. -- -- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or -- "semi-protected". -- -- ${PROTECTIONLOG} - a link to the protection log or the pending changes log, -- depending on the protection action. -- -- ${TALKPAGE} - a link to the talk page. If a section is specified, links -- straight to that talk page section. -- -- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to -- create a blurb like "This template is semi-protected", or "This article is -- move-protected until DD Month YYYY". -- -- ${VANDAL} - links for the specified username (or the root page name) -- using Module:Vandal-m. -- -- Functions -- -- For advanced users, it is possible to use Lua functions instead of strings -- in the banner config tables. Using functions gives flexibility that is not -- possible just by using parameters. Functions take two arguments, the -- protection object and the template arguments, and they must output a string. -- -- For example: -- -- text = function (protectionObj, args) -- if protectionObj.level == 'autoconfirmed' then -- return 'foo' -- else -- return 'bar' -- end -- end -- -- Some protection object properties and methods that may be useful: -- protectionObj.action - the protection action -- protectionObj.level - the protection level -- protectionObj.reason - the protection reason -- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set -- to indefinite, and the protection time in unix time if temporary. -- protectionObj.protectionDate - the protection date in unix time, or nil if -- unspecified. -- protectionObj.bannerConfig - the banner config found by the module. Beware -- of editing the config field used by the function, as it could create an -- infinite loop. -- protectionObj:isProtected - returns a boolean showing whether the page is -- protected. -- protectionObj:isTemporary - returns a boolean showing whether the expiry is -- temporary. -- protectionObj:isIncorrect - returns a boolean showing whether the protection -- template is incorrect. --]] -- The master banner data, used if no values have been found in banners or -- defaultBanners. masterBanner = { text = '${INTROBLURB}', explanation = '${EXPLANATIONBLURB}', tooltip = '${TOOLTIPBLURB}', link = '${IMAGELINK}', alt = 'Page ${PROTECTIONLEVEL}' }, -- The default banner data. This holds banner data for different protection -- levels. -- *required* - this table needs edit, move, autoreview and upload subtables. defaultBanners = { edit = {}, move = {}, autoreview = { default = { alt = 'Page protected with pending changes', tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users', image = 'Pending-protection-shackle.svg' } }, upload = {} }, -- The banner data. This holds banner data for different protection reasons. -- In fact, the reasons specified in this table control which reasons are -- valid inputs to the first positional parameter. -- -- There is also a non-standard "description" field that can be used for items -- in this table. This is a description of the protection reason for use in the -- module documentation. -- -- *required* - this table needs edit, move, autoreview and upload subtables. banners = { edit = { blp = { description = 'For pages protected to promote compliance with the' .. ' [[Wikipedia:Biographies of living persons' .. '|biographies of living persons]] policy', text = '${INTROFRAGMENT} to promote compliance with' .. ' [[Wikipedia:Biographies of living persons' .. "|Wikipedia's&nbsp;policy on&nbsp;the&nbsp;biographies" .. ' of&nbsp;living&nbsp;people]].', tooltip = '${TOOLTIPFRAGMENT} to promote compliance with the policy on' .. ' biographies of living persons', }, deceased = { description = 'For user pages of Wikipedia users who are deceased', text = '${INTROFRAGMENT} to prevent vandalism of a deceased' .. ' Wikipedian\'s user page.' .. ' A family member who wishes to edit this user page can use this' .. ' user\'s ${TALKPAGE} or submit a request to [[Wikipedia:VRT|the' .. ' Volunteer Response Team]].', tooltip = '${TOOLTIPFRAGMENT} because this Wikipedian is deceased' }, dmca = { description = 'For pages protected by the Wikimedia Foundation' .. ' due to [[Digital Millennium Copyright Act]] takedown requests', explanation = function (protectionObj, args) local ret = 'Pursuant to a rights owner notice under the Digital' .. ' Millennium Copyright Act (DMCA) regarding some content' .. ' in this article, the Wikimedia Foundation acted under' .. ' applicable law and took down and restricted the content' .. ' in question.' if args.notice then ret = ret .. ' A copy of the received notice can be found here: ' .. args.notice .. '.' end ret = ret .. ' For more information, including websites discussing' .. ' how to file a counter-notice, please see' .. " [[Wikipedia:Office actions]] and the article's ${TALKPAGE}." .. "'''Do not remove this template from the article until the" .. " restrictions are withdrawn'''." return ret end, image = 'Office-protection-shackle.svg', link = 'Wikipedia:Protection policy#office', }, dispute = { description = 'For pages protected due to editing disputes', text = function (protectionObj, args) -- Find the value of "disputes". local display = 'disputes' local disputes if args.section then disputes = string.format( '[[%s:%s#%s|%s]]', mw.site.namespaces[protectionObj.title.namespace].talk.name, protectionObj.title.text, args.section, display ) else disputes = display end -- Make the blurb, depending on the expiry. local msg if type(protectionObj.expiry) == 'number' then msg = '${INTROFRAGMENT} or until editing %s have been resolved.' else msg = '${INTROFRAGMENT} until editing %s have been resolved.' end return string.format(msg, disputes) end, explanation = "This protection is '''not''' an endorsement of the" .. ' ${CURRENTVERSION}. ${EXPLANATIONBLURB}', tooltip = '${TOOLTIPFRAGMENT} due to editing disputes', }, ecp = { description = 'For articles in topic areas authorized by' .. ' [[Wikipedia:Arbitration Committee|ArbCom]] or' .. ' meets the criteria for community use', alt = 'Extended-protected ${PAGETYPE}', }, mainpage = { description = 'For pages protected for being displayed on the [[Main Page]]', text = 'This file is currently' .. ' [[Wikipedia:This page is protected|protected]] from' .. ' editing because it is currently or will soon be displayed' .. ' on the [[Main Page]].', explanation = 'Images on the Main Page are protected due to their high' .. ' visibility. Please discuss any necessary changes on the ${TALKPAGE}.' .. '<br /><span style="font-size:90%;">' .. "'''Administrators:''' Once this image is definitely off the Main Page," .. ' please unprotect this file, or reduce to semi-protection,' .. ' as appropriate.</span>', }, office = { description = 'For pages protected by the Wikimedia Foundation', text = function (protectionObj, args) local ret = 'This ${PAGETYPE} is currently under the' .. ' scrutiny of the' .. ' [[Wikipedia:Office actions|Wikimedia Foundation Office]]' .. ' and is protected.' if protectionObj.protectionDate then ret = ret .. ' It has been protected since ${PROTECTIONDATE}.' end return ret end, explanation = "If you can edit this page, please discuss all changes and" .. " additions on the ${TALKPAGE} first. '''Do not remove protection from this" .. " page unless you are authorized by the Wikimedia Foundation to do" .. " so.'''", image = 'Office-protection-shackle.svg', link = 'Wikipedia:Protection policy#office', }, reset = { description = 'For pages protected by the Wikimedia Foundation and' .. ' "reset" to a bare-bones version', text = 'This ${PAGETYPE} is currently under the' .. ' scrutiny of the' .. ' [[Wikipedia:Office actions|Wikimedia Foundation Office]]' .. ' and is protected.', explanation = function (protectionObj, args) local ret = '' if protectionObj.protectionDate then ret = ret .. 'On ${PROTECTIONDATE} this ${PAGETYPE} was' else ret = ret .. 'This ${PAGETYPE} has been' end ret = ret .. ' reduced to a' .. ' simplified, "bare bones" version so that it may be completely' .. ' rewritten to ensure it meets the policies of' .. ' [[WP:NPOV|Neutral Point of View]] and [[WP:V|Verifiability]].' .. ' Standard Wikipedia policies will apply to its rewriting—which' .. ' will eventually be open to all editors—and will be strictly' .. ' enforced. The ${PAGETYPE} has been ${PROTECTIONLEVEL} while' .. ' it is being rebuilt.\n\n' .. 'Any insertion of material directly from' .. ' pre-protection revisions of the ${PAGETYPE} will be removed, as' .. ' will any material added to the ${PAGETYPE} that is not properly' .. ' sourced. The associated talk page(s) were also cleared on the' .. " same date.\n\n" .. "If you can edit this page, please discuss all changes and" .. " additions on the ${TALKPAGE} first. '''Do not override" .. " this action, and do not remove protection from this page," .. " unless you are authorized by the Wikimedia Foundation" .. " to do so. No editor may remove this notice.'''" return ret end, image = 'Office-protection-shackle.svg', link = 'Wikipedia:Protection policy#office', }, sock = { description = 'For pages protected due to' .. ' [[Wikipedia:Sock puppetry|sock puppetry]]', text = '${INTROFRAGMENT} to prevent [[Wikipedia:Sock puppetry|sock puppets]] of' .. ' [[Wikipedia:Blocking policy|blocked]] or' .. ' [[Wikipedia:Banning policy|banned users]]' .. ' from editing it.', tooltip = '${TOOLTIPFRAGMENT} to prevent sock puppets of blocked or banned users from' .. ' editing it', }, template = { description = 'For [[Wikipedia:High-risk templates|high-risk]]' .. ' templates and Lua modules', text = 'This is a permanently [[Wikipedia:Protection policy|protected]] ${PAGETYPE},' .. ' as it is [[Wikipedia:High-risk templates|high-risk]].', explanation = 'Please discuss any changes on the ${TALKPAGE}; you may' .. ' ${EDITREQUEST} to ask an' .. ' [[Wikipedia:Administrators|administrator]] or' .. ' [[Wikipedia:Template editor|template editor]] to make an edit if' .. ' it is [[Help:Minor edit#When to mark an edit as a minor edit' .. '|uncontroversial]] or supported by' .. ' [[Wikipedia:Consensus|consensus]]. You can also' .. ' [[Wikipedia:Requests for page protection|request]] that the page be' .. ' unprotected.', tooltip = 'This high-risk ${PAGETYPE} is permanently ${PROTECTIONLEVEL}' .. ' to prevent vandalism', alt = 'Permanently protected ${PAGETYPE}', }, usertalk = { description = 'For pages protected against disruptive edits by a' .. ' particular user', text = '${INTROFRAGMENT} to prevent ${VANDAL} from using it to make disruptive edits,' .. ' such as abusing the' .. ' &#123;&#123;[[Template:unblock|unblock]]&#125;&#125; template.', explanation = 'If you cannot edit this user talk page and you need to' .. ' make a change or leave a message, you can' .. ' [[Wikipedia:Requests for page protection' .. '#Current requests for edits to a protected page' .. '|request an edit]],' .. ' [[Wikipedia:Requests for page protection' .. '#Current requests for reduction in protection level' .. '|request unprotection]],' .. ' [[Special:Userlogin|log in]],' .. ' or [[Special:UserLogin/signup|create an account]].', }, vandalism = { description = 'For pages protected against' .. ' [[Wikipedia:Vandalism|vandalism]]', text = '${INTROFRAGMENT} due to [[Wikipedia:Vandalism|vandalism]].', explanation = function (protectionObj, args) local ret = '' if protectionObj.level == 'sysop' then ret = ret .. "This protection is '''not''' an endorsement of the" .. ' ${CURRENTVERSION}. ' end return ret .. '${EXPLANATIONBLURB}' end, tooltip = '${TOOLTIPFRAGMENT} due to vandalism', } }, move = { dispute = { description = 'For pages protected against page moves due to' .. ' disputes over the page title', explanation = "This protection is '''not''' an endorsement of the" .. ' ${CURRENTVERSION}. ${EXPLANATIONBLURB}', image = 'Move-protection-shackle.svg' }, vandalism = { description = 'For pages protected against' .. ' [[Wikipedia:Vandalism#Page-move vandalism' .. ' |page-move vandalism]]' } }, autoreview = {}, upload = {} }, -------------------------------------------------------------------------------- -- -- GENERAL DATA TABLES -- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Protection blurbs -------------------------------------------------------------------------------- -- This table produces the protection blurbs available with the -- ${PROTECTIONBLURB} parameter. It is sorted by protection action and -- protection level, and is checked by the module in the following order: -- 1. page's protection action, page's protection level -- 2. page's protection action, default protection level -- 3. "edit" protection action, default protection level -- -- It is possible to use banner parameters inside this table. -- *required* - this table needs edit, move, autoreview and upload subtables. protectionBlurbs = { edit = { default = 'इमं ${PAGETYPE} नव वा [[Wikipedia:Protection policy#full|' .. 'अननुपलिखित]] योजकेहि सोधेतुं एतरहि न अनुञ्ञातं', templateeditor = 'इमं ${PAGETYPE} नव वा [[Wikipedia:Protection policy#template' .. 'अननुपलिखित]] योजकेहि सोधेतुं एतरहि न अनुञ्ञातं', autoconfirmed = 'Editing of this ${PAGETYPE} by [[Wikipedia:User access' .. ' levels#New users|new]] or [[Wikipedia:User access levels#Unregistered' .. ' users|unregistered]] users is currently [[Wikipedia:Protection' .. ' policy#semi|disabled]]', extendedconfirmed = 'This ${PAGETYPE} is currently under [[Wikipedia:Protection' .. ' policy#extended|extended confirmed protection]]', }, move = { default = 'This ${PAGETYPE} is currently [[Wikipedia:Protection policy#Move' .. ' protection|protected]] from [[Help:Moving a page|page moves]]' }, autoreview = { default = 'All edits made to this ${PAGETYPE} by' .. ' [[Wikipedia:User access levels#New users|new]] or' .. ' [[Wikipedia:User access levels#Unregistered users|unregistered]]' .. ' users are currently' .. ' [[Wikipedia:Pending changes|subject to review]]' }, upload = { default = 'Uploading new versions of this ${PAGETYPE} is currently disabled' } }, -------------------------------------------------------------------------------- -- Explanation blurbs -------------------------------------------------------------------------------- -- This table produces the explanation blurbs available with the -- ${EXPLANATIONBLURB} parameter. It is sorted by protection action, -- protection level, and whether the page is a talk page or not. If the page is -- a talk page it will have a talk key of "talk"; otherwise it will have a talk -- key of "subject". The table is checked in the following order: -- 1. page's protection action, page's protection level, page's talk key -- 2. page's protection action, page's protection level, default talk key -- 3. page's protection action, default protection level, page's talk key -- 4. page's protection action, default protection level, default talk key -- -- It is possible to use banner parameters inside this table. -- *required* - this table needs edit, move, autoreview and upload subtables. explanationBlurbs = { edit = { autoconfirmed = { subject = 'वित्थारत्थाय [[:en:Wikipedia:Protection policy|' .. 'रक्खननीतिं]] च ${PROTECTIONLOG} च पस्सथ॥ यदि' .. ' तुवं इमं ${PAGETYPE} सोधेतुं न सक्कोसि तथापि परिवत्तनं कातुं इच्छसि' .. ' तेन हि सुत्तेन ${EDITREQUEST}, ${TALKPAGE},सम्भासनं' .. ' [[:en:Wikipedia:Requests for page protection' .. '#Current requests for reduction in protection level' .. '|रक्खनविमोचनत्थाय याचनं]]। [[Special:Userlogin|अक्खत्तपवेसनं]]। वा' .. ' [[Special:UserLogin/signup|अक्खत्तनिम्माणं कातुं सक्कोसि॥]]', default = 'वित्थारत्थाय [[:en:Wikipedia:Protection policy|' .. 'रक्खननीतिं]] च ${PROTECTIONLOG} च पस्सथ॥ यदि' .. ' तुवं इमं ${PAGETYPE} सोधेतुं न सक्कोसि तथापि परिवत्तनं कातुं इच्छसि' .. ' [[Wikipedia:तेन हि सुत्तेन' .. '#Current requests for reduction in protection level' .. '|रक्खनविमोचनत्थाय याचनं]]। [[Special:Userlogin|अक्खत्तपवेसनं]]। वा' .. ' [[Special:UserLogin/signup|अक्खत्तनिम्माणं]] कातुं सक्कोसि॥', }, extendedconfirmed = { default = 'Extended confirmed protection prevents edits from all unregistered editors' .. ' and registered users with fewer than 30 days tenure and 500 edits.' .. ' The [[Wikipedia:Protection policy#extended|policy on community use]]' .. ' specifies that extended confirmed protection can be applied to combat' .. ' disruption, if semi-protection has proven to be ineffective.' .. ' Extended confirmed protection may also be applied to enforce' .. ' [[Wikipedia:Arbitration Committee|arbitration sanctions]].' .. ' Please discuss any changes on the ${TALKPAGE}; you may' .. ' ${EDITREQUEST} to ask for uncontroversial changes supported by' .. ' [[Wikipedia:Consensus|consensus]].' }, default = { subject = 'वित्थारत्थाय [[:en:Wikipedia:Protection policy|' .. 'रक्खननीतिं]] च ${PROTECTIONLOG} च पस्सथ॥' .. ' Please discuss any changes on the ${TALKPAGE}; you' .. ' may ${EDITREQUEST} to ask an' .. ' [[Wikipedia:Administrators|administrator]] to make an edit if it' .. ' is [[Help:Minor edit#When to mark an edit as a minor edit' .. '|uncontroversial]] or supported by [[Wikipedia:Consensus' .. '|consensus]]. You may also [[Wikipedia:Requests for' .. ' page protection#Current requests for reduction in protection level' .. '|request]] that this page be unprotected.', default = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' You may [[Wikipedia:Requests for page' .. ' protection#Current requests for edits to a protected page|request an' .. ' edit]] to this page, or [[Wikipedia:Requests for' .. ' page protection#Current requests for reduction in protection level' .. '|ask]] for it to be unprotected.' } }, move = { default = { subject = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' The page may still be edited but cannot be moved' .. ' until unprotected. Please discuss any suggested moves on the' .. ' ${TALKPAGE} or at [[Wikipedia:Requested moves]]. You can also' .. ' [[Wikipedia:Requests for page protection|request]] that the page be' .. ' unprotected.', default = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' The page may still be edited but cannot be moved' .. ' until unprotected. Please discuss any suggested moves at' .. ' [[Wikipedia:Requested moves]]. You can also' .. ' [[Wikipedia:Requests for page protection|request]] that the page be' .. ' unprotected.' } }, autoreview = { default = { default = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' Edits to this ${PAGETYPE} by new and unregistered users' .. ' will not be visible to readers until they are accepted by' .. ' a reviewer. To avoid the need for your edits to be' .. ' reviewed, you may' .. ' [[Wikipedia:Requests for page protection' .. '#Current requests for reduction in protection level' .. '|request unprotection]], [[Special:Userlogin|log in]], or' .. ' [[Special:UserLogin/signup|create an account]].' }, }, upload = { default = { default = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' The page may still be edited but new versions of the file' .. ' cannot be uploaded until it is unprotected. You can' .. ' request that a new version be uploaded by using a' .. ' [[Wikipedia:Edit requests|protected edit request]], or you' .. ' can [[Wikipedia:Requests for page protection|request]]' .. ' that the file be unprotected.' } } }, -------------------------------------------------------------------------------- -- Protection levels -------------------------------------------------------------------------------- -- This table provides the data for the ${PROTECTIONLEVEL} parameter, which -- produces a short label for different protection levels. It is sorted by -- protection action and protection level, and is checked in the following -- order: -- 1. page's protection action, page's protection level -- 2. page's protection action, default protection level -- 3. "edit" protection action, default protection level -- -- It is possible to use banner parameters inside this table. -- *required* - this table needs edit, move, autoreview and upload subtables. protectionLevels = { edit = { default = 'protected', templateeditor = 'template-protected', extendedconfirmed = 'extended-confirmed-protected', autoconfirmed = 'semi-protected', }, move = { default = 'move-protected' }, autoreview = { }, upload = { default = 'upload-protected' } }, -------------------------------------------------------------------------------- -- Images -------------------------------------------------------------------------------- -- This table lists different padlock images for each protection action and -- protection level. It is used if an image is not specified in any of the -- banner data tables, and if the page does not satisfy the conditions for using -- the ['image-filename-indef'] image. It is checked in the following order: -- 1. page's protection action, page's protection level -- 2. page's protection action, default protection level images = { edit = { default = 'Full-protection-shackle.svg', templateeditor = 'Template-protection-shackle.svg', extendedconfirmed = 'Extended-protection-shackle.svg', autoconfirmed = 'Semi-protection-shackle.svg' }, move = { default = 'Move-protection-shackle.svg', }, autoreview = { default = 'Pending-protection-shackle.svg' }, upload = { default = 'Upload-protection-shackle.svg' } }, -- Pages with a reason specified in this table will show the special "indef" -- padlock, defined in the 'image-filename-indef' message, if no expiry is set. indefImageReasons = { template = true }, -------------------------------------------------------------------------------- -- Image links -------------------------------------------------------------------------------- -- This table provides the data for the ${IMAGELINK} parameter, which gets -- the image link for small padlock icons based on the page's protection action -- and protection level. It is checked in the following order: -- 1. page's protection action, page's protection level -- 2. page's protection action, default protection level -- 3. "edit" protection action, default protection level -- -- It is possible to use banner parameters inside this table. -- *required* - this table needs edit, move, autoreview and upload subtables. imageLinks = { edit = { default = 'Wikipedia:Protection policy#full', templateeditor = 'Wikipedia:Protection policy#template', extendedconfirmed = 'Wikipedia:Protection policy#extended', autoconfirmed = 'Wikipedia:Protection policy#semi' }, move = { default = 'Wikipedia:Protection policy#move' }, autoreview = { default = 'Wikipedia:Protection policy#pending' }, upload = { default = 'Wikipedia:Protection policy#upload' } }, -------------------------------------------------------------------------------- -- Padlock indicator names -------------------------------------------------------------------------------- -- This table provides the "name" attribute for the <indicator> extension tag -- with which small padlock icons are generated. All indicator tags on a page -- are displayed in alphabetical order based on this attribute, and with -- indicator tags with duplicate names, the last tag on the page wins. -- The attribute is chosen based on the protection action; table keys must be a -- protection action name or the string "default". padlockIndicatorNames = { autoreview = 'pp-autoreview', default = 'pp-default' }, -------------------------------------------------------------------------------- -- Protection categories -------------------------------------------------------------------------------- --[[ -- The protection categories are stored in the protectionCategories table. -- Keys to this table are made up of the following strings: -- -- 1. the expiry date -- 2. the namespace -- 3. the protection reason (e.g. "dispute" or "vandalism") -- 4. the protection level (e.g. "sysop" or "autoconfirmed") -- 5. the action (e.g. "edit" or "move") -- -- When the module looks up a category in the table, first it will will check to -- see a key exists that corresponds to all five parameters. For example, a -- user page semi-protected from vandalism for two weeks would have the key -- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module -- changes the first part of the key to "all" and checks the table again. It -- keeps checking increasingly generic key combinations until it finds the -- field, or until it reaches the key "all-all-all-all-all". -- -- The module uses a binary matrix to determine the order in which to search. -- This is best demonstrated by a table. In this table, the "0" values -- represent "all", and the "1" values represent the original data (e.g. -- "indef" or "file" or "vandalism"). -- -- expiry namespace reason level action -- order -- 1 1 1 1 1 1 -- 2 0 1 1 1 1 -- 3 1 0 1 1 1 -- 4 0 0 1 1 1 -- 5 1 1 0 1 1 -- 6 0 1 0 1 1 -- 7 1 0 0 1 1 -- 8 0 0 0 1 1 -- 9 1 1 1 0 1 -- 10 0 1 1 0 1 -- 11 1 0 1 0 1 -- 12 0 0 1 0 1 -- 13 1 1 0 0 1 -- 14 0 1 0 0 1 -- 15 1 0 0 0 1 -- 16 0 0 0 0 1 -- 17 1 1 1 1 0 -- 18 0 1 1 1 0 -- 19 1 0 1 1 0 -- 20 0 0 1 1 0 -- 21 1 1 0 1 0 -- 22 0 1 0 1 0 -- 23 1 0 0 1 0 -- 24 0 0 0 1 0 -- 25 1 1 1 0 0 -- 26 0 1 1 0 0 -- 27 1 0 1 0 0 -- 28 0 0 1 0 0 -- 29 1 1 0 0 0 -- 30 0 1 0 0 0 -- 31 1 0 0 0 0 -- 32 0 0 0 0 0 -- -- In this scheme the action has the highest priority, as it is the last -- to change, and the expiry has the least priority, as it changes the most. -- The priorities of the expiry, the protection level and the action are -- fixed, but the priorities of the reason and the namespace can be swapped -- through the use of the cfg.bannerDataNamespaceHasPriority table. --]] -- If the reason specified to the template is listed in this table, -- namespace data will take priority over reason data in the protectionCategories -- table. reasonsWithNamespacePriority = { vandalism = true, }, -- The string to use as a namespace key for the protectionCategories table for each -- namespace number. categoryNamespaceKeys = { [ 2] = 'user', [ 3] = 'user', [ 4] = 'project', [ 6] = 'file', [ 8] = 'mediawiki', [ 10] = 'template', [ 12] = 'project', [ 14] = 'category', [100] = 'portal', [828] = 'module', }, protectionCategories = { ['all|all|all|all|all'] = 'सब्बसो रक्खित वीकीपीःदीःयाः पिट्ठानि', ['all|all|office|all|all'] = 'Wikipedia Office-protected pages', ['all|all|reset|all|all'] = 'Wikipedia Office-protected pages', ['all|all|dmca|all|all'] = 'Wikipedia Office-protected pages', ['all|all|mainpage|all|all'] = 'Wikipedia fully protected main page files', ['all|all|all|extendedconfirmed|all'] = 'Wikipedia extended-confirmed-protected pages', ['all|all|ecp|extendedconfirmed|all'] = 'Wikipedia extended-confirmed-protected pages', ['all|template|all|all|edit'] = 'सब्बसो रक्खित वीकीपीःदीःयाः पटिरूप', ['all|all|all|autoconfirmed|edit'] = 'Wikipedia semi-protected pages', ['indef|all|all|autoconfirmed|edit'] = 'Wikipedia indefinitely semi-protected pages', ['all|all|blp|autoconfirmed|edit'] = 'Wikipedia indefinitely semi-protected biographies of living people', ['temp|all|blp|autoconfirmed|edit'] = 'Wikipedia temporarily semi-protected biographies of living people', ['all|all|dispute|autoconfirmed|edit'] = 'Wikipedia pages semi-protected due to dispute', ['all|all|sock|autoconfirmed|edit'] = 'Wikipedia pages semi-protected from banned users', ['all|all|vandalism|autoconfirmed|edit'] = 'Wikipedia pages semi-protected against vandalism', ['all|category|all|autoconfirmed|edit'] = 'Wikipedia semi-protected categories', ['all|file|all|autoconfirmed|edit'] = 'Wikipedia semi-protected files', ['all|portal|all|autoconfirmed|edit'] = 'Wikipedia semi-protected portals', ['all|project|all|autoconfirmed|edit'] = 'Wikipedia semi-protected project pages', ['all|talk|all|autoconfirmed|edit'] = 'Wikipedia semi-protected talk pages', ['all|template|all|autoconfirmed|edit'] = 'Wikipedia semi-protected templates', ['all|user|all|autoconfirmed|edit'] = 'Wikipedia semi-protected user and user talk pages', ['all|all|all|templateeditor|move'] = 'Wikipedia template-protected pages other than templates and modules', ['all|all|all|templateeditor|edit'] = 'Wikipedia template-protected pages other than templates and modules', ['all|template|all|templateeditor|edit'] = 'Wikipedia template-protected templates', ['all|template|all|templateeditor|move'] = 'Wikipedia template-protected templates', -- move-protected templates ['all|all|blp|sysop|edit'] = 'Wikipedia indefinitely protected biographies of living people', ['temp|all|blp|sysop|edit'] = 'Wikipedia temporarily protected biographies of living people', ['all|all|dispute|sysop|edit'] = 'Wikipedia pages protected due to dispute', ['all|all|sock|sysop|edit'] = 'Wikipedia pages protected from banned users', ['all|all|vandalism|sysop|edit'] = 'Wikipedia pages protected against vandalism', ['all|category|all|sysop|edit'] = 'Wikipedia fully protected categories', ['all|file|all|sysop|edit'] = 'Wikipedia fully protected files', ['all|project|all|sysop|edit'] = 'Wikipedia fully protected project pages', ['all|talk|all|sysop|edit'] = 'Wikipedia fully protected talk pages', ['all|template|all|extendedconfirmed|edit'] = 'Wikipedia extended-confirmed-protected templates', ['all|template|all|extendedconfirmed|move'] = 'Wikipedia extended-confirmed-protected templates', ['all|template|all|sysop|edit'] = 'Wikipedia fully protected templates', ['all|user|all|sysop|edit'] = 'Wikipedia fully protected user and user talk pages', ['all|module|all|all|edit'] = 'Wikipedia fully protected modules', ['all|module|all|templateeditor|edit'] = 'Wikipedia template-protected modules', ['all|module|all|extendedconfirmed|edit'] = 'Wikipedia extended-confirmed-protected modules', ['all|module|all|autoconfirmed|edit'] = 'Wikipedia semi-protected modules', ['all|all|all|sysop|move'] = 'Wikipedia move-protected pages', ['indef|all|all|sysop|move'] = 'Wikipedia indefinitely move-protected pages', ['all|all|dispute|sysop|move'] = 'Wikipedia pages move-protected due to dispute', ['all|all|vandalism|sysop|move'] = 'Wikipedia pages move-protected due to vandalism', ['all|portal|all|sysop|move'] = 'Wikipedia move-protected portals', ['all|project|all|sysop|move'] = 'Wikipedia move-protected project pages', ['all|talk|all|sysop|move'] = 'Wikipedia move-protected talk pages', ['all|template|all|sysop|move'] = 'Wikipedia move-protected templates', ['all|user|all|sysop|move'] = 'Wikipedia move-protected user and user talk pages', ['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages', ['all|file|all|all|upload'] = 'Wikipedia upload-protected files', }, -------------------------------------------------------------------------------- -- Expiry category config -------------------------------------------------------------------------------- -- This table configures the expiry category behaviour for each protection -- action. -- * If set to true, setting that action will always categorise the page if -- an expiry parameter is not set. -- * If set to false, setting that action will never categorise the page. -- * If set to nil, the module will categorise the page if: -- 1) an expiry parameter is not set, and -- 2) a reason is provided, and -- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck -- table. expiryCheckActions = { edit = nil, move = false, autoreview = true, upload = false }, reasonsWithoutExpiryCheck = { blp = true, template = true, }, -------------------------------------------------------------------------------- -- Pagetypes -------------------------------------------------------------------------------- -- This table produces the page types available with the ${PAGETYPE} parameter. -- Keys are namespace numbers, or the string "default" for the default value. pagetypes = { [0] = 'article', [6] = 'file', [10] = 'template', [14] = 'category', [828] = 'module', default = 'page' }, -------------------------------------------------------------------------------- -- Strings marking indefinite protection -------------------------------------------------------------------------------- -- This table contains values passed to the expiry parameter that mean the page -- is protected indefinitely. indefStrings = { ['indef'] = true, ['indefinite'] = true, ['indefinitely'] = true, ['infinite'] = true, }, -------------------------------------------------------------------------------- -- Group hierarchy -------------------------------------------------------------------------------- -- This table maps each group to all groups that have a superset of the original -- group's page editing permissions. hierarchy = { sysop = {}, reviewer = {'sysop'}, filemover = {'sysop'}, templateeditor = {'sysop'}, extendedconfirmed = {'sysop'}, autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'}, user = {'autoconfirmed'}, ['*'] = {'user'} }, -------------------------------------------------------------------------------- -- Wrapper templates and their default arguments -------------------------------------------------------------------------------- -- This table contains wrapper templates used with the module, and their -- default arguments. Templates specified in this table should contain the -- following invocation, and no other template content: -- -- {{#invoke:Protection banner|main}} -- -- If other content is desired, it can be added between -- <noinclude>...</noinclude> tags. -- -- When a user calls one of these wrapper templates, they will use the -- default arguments automatically. However, users can override any of the -- arguments. wrappers = { ['Template:Protected page'] = {}, ['Template:Extended confirmed–protected'] = {'ecp'}, ['Template:Protected biography of a living person'] = {'blp'}, ['Template:Protected due to a dispute'] = {'dispute'}, ['Template:Move-protected'] = {action = 'move', catonly = 'yes'}, ['Template:Move-protected due to a dispute'] = {'dispute', action = 'move', catonly = 'yes'}, ['Template:Move-protected due to vandalism'] = {'vandalism', action = 'move', catonly = 'yes'}, ['Template:Office-protected'] = {'office'}, ['Template:Pending changes–protected'] = {action = 'autoreview', small = true}, ['Template:Semi-protected indefinitely'] = {small = true}, ['Template:Protected due to sockpuppetry'] = {'sock'}, ['Template:Template-protected'] = {'template', small = true}, ['Template:Upload-protected'] = {action = 'upload'}, ['Template:Protected talk page of a blocked user'] = {'usertalk'}, ['Template:Protected due to vandalism'] = {'vandalism'}, }, -------------------------------------------------------------------------------- -- -- MESSAGES -- -------------------------------------------------------------------------------- msg = { -------------------------------------------------------------------------------- -- Intro blurb and intro fragment -------------------------------------------------------------------------------- -- These messages specify what is produced by the ${INTROBLURB} and -- ${INTROFRAGMENT} parameters. If the protection is temporary they use the -- intro-blurb-expiry or intro-fragment-expiry, and if not they use -- intro-blurb-noexpiry or intro-fragment-noexpiry. -- It is possible to use banner parameters in these messages. ['intro-blurb-expiry'] = '${PROTECTIONBLURB} until ${EXPIRY}.', ['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}.', ['intro-fragment-expiry'] = '${PROTECTIONBLURB} until ${EXPIRY},', ['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}', -------------------------------------------------------------------------------- -- Tooltip blurb -------------------------------------------------------------------------------- -- These messages specify what is produced by the ${TOOLTIPBLURB} parameter. -- If the protection is temporary the tooltip-blurb-expiry message is used, and -- if not the tooltip-blurb-noexpiry message is used. -- It is possible to use banner parameters in these messages. ['tooltip-blurb-expiry'] = 'इमं ${PAGETYPE} याव ${PROTECTIONLEVEL} ${EXPIRY}.', ['tooltip-blurb-noexpiry'] = 'इमं ${PAGETYPE} याव ${PROTECTIONLEVEL}.', ['tooltip-fragment-expiry'] = 'इमं ${PAGETYPE} याव ${PROTECTIONLEVEL} until ${EXPIRY},', ['tooltip-fragment-noexpiry'] = 'इमं ${PAGETYPE} याव ${PROTECTIONLEVEL}', -------------------------------------------------------------------------------- -- Special explanation blurb -------------------------------------------------------------------------------- -- An explanation blurb for pages that cannot be unprotected, e.g. for pages -- in the MediaWiki namespace. -- It is possible to use banner parameters in this message. ['explanation-blurb-nounprotect'] = 'See the [[Wikipedia:Protection policy|' .. 'protection policy]] and ${PROTECTIONLOG} for more details.' .. ' Please discuss any changes on the ${TALKPAGE}; you' .. ' may ${EDITREQUEST} to ask an' .. ' [[Wikipedia:Administrators|administrator]] to make an edit if it' .. ' is [[Help:Minor edit#When to mark an edit as a minor edit' .. '|uncontroversial]] or supported by [[Wikipedia:Consensus' .. '|consensus]].', -------------------------------------------------------------------------------- -- Protection log display values -------------------------------------------------------------------------------- -- These messages determine the display values for the protection log link -- or the pending changes log link produced by the ${PROTECTIONLOG} parameter. -- It is possible to use banner parameters in these messages. ['protection-log-display'] = 'protection log', ['pc-log-display'] = 'pending changes log', -------------------------------------------------------------------------------- -- Current version display values -------------------------------------------------------------------------------- -- These messages determine the display values for the page history link -- or the move log link produced by the ${CURRENTVERSION} parameter. -- It is possible to use banner parameters in these messages. ['current-version-move-display'] = 'current title', ['current-version-edit-display'] = 'current version', -------------------------------------------------------------------------------- -- Talk page -------------------------------------------------------------------------------- -- This message determines the display value of the talk page link produced -- with the ${TALKPAGE} parameter. -- It is possible to use banner parameters in this message. ['talk-page-link-display'] = 'talk page', -------------------------------------------------------------------------------- -- Edit requests -------------------------------------------------------------------------------- -- This message determines the display value of the edit request link produced -- with the ${EDITREQUEST} parameter. -- It is possible to use banner parameters in this message. ['edit-request-display'] = 'submit an edit request', -------------------------------------------------------------------------------- -- Expiry date format -------------------------------------------------------------------------------- -- This is the format for the blurb expiry date. It should be valid input for -- the first parameter of the #time parser function. ['expiry-date-format'] = 'F j, Y "at" H:i e', -------------------------------------------------------------------------------- -- Tracking categories -------------------------------------------------------------------------------- -- These messages determine which tracking categories the module outputs. ['tracking-category-incorrect'] = 'Wikipedia pages with incorrect protection templates', ['tracking-category-template'] = 'Wikipedia template-protected pages other than templates and modules', -------------------------------------------------------------------------------- -- Images -------------------------------------------------------------------------------- -- These are images that are not defined by their protection action and protection level. ['image-filename-indef'] = 'Full-protection-shackle.svg', ['image-filename-default'] = 'Transparent.gif', -------------------------------------------------------------------------------- -- End messages -------------------------------------------------------------------------------- } -------------------------------------------------------------------------------- -- End configuration -------------------------------------------------------------------------------- } omztmwhw2ducl26r268agi0sz20oqy1 Module:File link 828 7363 103782 2026-09-04T05:47:39Z 咽頭べさ 6149 Created page with "-- This module provides a library for formatting file wikilinks. local yesno = require('Module:Yesno') local checkType = require('libraryUtil').checkType local p = {} function p._main(args) checkType('_main', 1, args, 'table') -- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our -- own function to get the right error level. local function checkArg(key, val, level) if type(val) ~= 'string' then error(string.format( "type error in..." 103782 Scribunto text/plain -- This module provides a library for formatting file wikilinks. local yesno = require('Module:Yesno') local checkType = require('libraryUtil').checkType local p = {} function p._main(args) checkType('_main', 1, args, 'table') -- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our -- own function to get the right error level. local function checkArg(key, val, level) if type(val) ~= 'string' then error(string.format( "type error in '%s' parameter of '_main' (expected string, got %s)", key, type(val) ), level) end end local ret = {} -- Adds a positional parameter to the buffer. local function addPositional(key) local val = args[key] if not val then return nil end checkArg(key, val, 4) ret[#ret + 1] = val end -- Adds a named parameter to the buffer. We assume that the parameter name -- is the same as the argument key. local function addNamed(key) local val = args[key] if not val then return nil end checkArg(key, val, 4) ret[#ret + 1] = key .. '=' .. val end -- Filename checkArg('file', args.file, 3) ret[#ret + 1] = 'File:' .. args.file -- Format if args.format then checkArg('format', args.format) if args.formatfile then checkArg('formatfile', args.formatfile) ret[#ret + 1] = args.format .. '=' .. args.formatfile else ret[#ret + 1] = args.format end end -- Border if yesno(args.border) then ret[#ret + 1] = 'border' end addPositional('location') addPositional('alignment') addPositional('size') addNamed('upright') addNamed('link') addNamed('alt') addNamed('page') addNamed('class') addNamed('lang') addNamed('start') addNamed('end') addNamed('thumbtime') addPositional('caption') return string.format('[[%s]]', table.concat(ret, '|')) end function p.main(frame) local origArgs = require('Module:Arguments').getArgs(frame, { wrappers = 'Template:File link' }) if not origArgs.file then error("'file' parameter missing from [[Template:File link]]", 0) end -- Copy the arguments that were passed to a new table to avoid looking up -- every possible parameter in the frame object. local args = {} for k, v in pairs(origArgs) do -- Make _BLANK a special argument to add a blank parameter. For use in -- conditional templates etc. it is useful for blank arguments to be -- ignored, but we still need a way to specify them so that we can do -- things like [[File:Example.png|link=]]. if v == '_BLANK' then v = '' end args[k] = v end return p._main(args) end return p bzc22v133v9z5yc4aisazripn6l94p8 Module:Effective protection level 828 7364 103783 2026-09-04T05:49:30Z 咽頭べさ 6149 Created page with "local p = {} -- Returns the permission required to perform a given action on a given title. -- If no title is specified, the title of the page being displayed is used. function p._main(action, pagename) local title if type(pagename) == 'table' and pagename.prefixedText then title = pagename elseif pagename then title = mw.title.new(pagename) else title = mw.title.getCurrentTitle() end pagename = title.prefixedText if action == 'autoreview' then local level..." 103783 Scribunto text/plain local p = {} -- Returns the permission required to perform a given action on a given title. -- If no title is specified, the title of the page being displayed is used. function p._main(action, pagename) local title if type(pagename) == 'table' and pagename.prefixedText then title = pagename elseif pagename then title = mw.title.new(pagename) else title = mw.title.getCurrentTitle() end pagename = title.prefixedText if action == 'autoreview' then local level = mw.ext.FlaggedRevs.getStabilitySettings(title) level = level and level.autoreview if level == 'review' then return 'reviewer' elseif level ~= '' then return level else return nil -- not '*'. a page not being PC-protected is distinct from it being PC-protected with anyone able to review. also not '', as that would mean PC-protected but nobody can review end elseif action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' and action ~= 'undelete' then error( 'First parameter must be one of edit, move, create, upload, undelete, autoreview', 2 ) end if title.namespace == 8 then -- MediaWiki namespace if title.text:sub(-3) == '.js' or title.text:sub(-4) == '.css' or title.contentModel == 'javascript' or title.contentModel == 'css' then -- site JS or CSS page return 'interfaceadmin' elseif title.baseText == "Gadgets-definition" then return 'interfaceadmin' else -- any non-JS/CSS MediaWiki page return 'sysop' end elseif title.namespace == 2 and title.isSubpage then if title.contentModel == 'javascript' or title.contentModel == 'css' then -- user JS or CSS page return 'interfaceadmin' elseif title.contentModel == 'json' then -- user JSON page return 'sysop' end end if action == 'undelete' then return 'sysop' end local level = title.protectionLevels[action] and title.protectionLevels[action][1] if level == 'sysop' or level == 'editprotected' then return 'sysop' elseif title.cascadingProtection.restrictions[action] and title.cascadingProtection.restrictions[action][1] then -- used by a cascading-protected page return 'sysop' elseif level == 'templateeditor' then return 'templateeditor' elseif action == 'move' then local blacklistentry = mw.ext.TitleBlacklist.test('edit', pagename) -- Testing action edit is correct, since this is for the source page. The target page name gets tested with action move. if blacklistentry and not blacklistentry.params.autoconfirmed then return 'templateeditor' elseif title.namespace == 6 then return 'filemover' elseif level == 'extendedconfirmed' then return 'extendedconfirmed' else return 'autoconfirmed' end end local blacklistentry = mw.ext.TitleBlacklist.test(action, pagename) if blacklistentry then if not blacklistentry.params.autoconfirmed then return 'templateeditor' elseif level == 'extendedconfirmed' then return 'extendedconfirmed' else return 'autoconfirmed' end elseif level == 'editsemiprotected' then -- create-semiprotected pages return this for some reason return 'autoconfirmed' elseif level then return level elseif action == 'upload' then return 'autoconfirmed' elseif action == 'create' and title.namespace % 2 == 0 and title.namespace ~= 118 then -- You need to be registered, but not autoconfirmed, to create non-talk pages other than drafts if title.namespace == 0 then return 'autoconfirmed' -- Per [[WP:ACPERM]], you need to be autoconfirmed to create pages in mainspace end return 'user' else return '*' end end setmetatable(p, { __index = function(t, k) return function(frame) return t._main(k, frame.args[1]) end end }) return p nacj9lsnya0896kpkyuy2onbc6mm6xw Module:Effective protection expiry 828 7365 103786 2026-09-04T05:56:30Z 咽頭べさ 6149 Created page with "local p = {} -- Returns the expiry of a restriction of an action on a given title, or unknown if it cannot be known. -- If no title is specified, the title of the page being displayed is used. function p._main(action, pagename) local title if type(pagename) == 'table' and pagename.prefixedText then title = pagename elseif pagename then title = mw.title.new(pagename) else title = mw.title.getCurrentTitle() end pagename = title.prefixedText if action == 'auto..." 103786 Scribunto text/plain local p = {} -- Returns the expiry of a restriction of an action on a given title, or unknown if it cannot be known. -- If no title is specified, the title of the page being displayed is used. function p._main(action, pagename) local title if type(pagename) == 'table' and pagename.prefixedText then title = pagename elseif pagename then title = mw.title.new(pagename) else title = mw.title.getCurrentTitle() end pagename = title.prefixedText if action == 'autoreview' then local stabilitySettings = mw.ext.FlaggedRevs.getStabilitySettings(title) return stabilitySettings and stabilitySettings.expiry or 'unknown' elseif action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' then error( 'First parameter must be one of edit, move, create, upload, autoreview', 2 ) end local rawExpiry = mw.getCurrentFrame():callParserFunction('PROTECTIONEXPIRY', action, pagename) if rawExpiry == 'infinity' then return 'infinity' elseif rawExpiry == '' then return 'unknown' else local year, month, day, hour, minute, second = rawExpiry:match( '^(%d%d%d%d)(%d%d)(%d%d)(%d%d)(%d%d)(%d%d)$' ) if year then return string.format( '%s-%s-%sT%s:%s:%s', year, month, day, hour, minute, second ) else error('internal error in Module:Effective protection expiry; malformed expiry timestamp') end end end setmetatable(p, { __index = function(t, k) return function(frame) return t._main(k, frame.args[1]) end end }) return p i1wms02y1w048cq6uttka18a5pjzp63 विभाग:वीकीपीःदीःयाः सोधनउपकारानि 14 7366 103788 2026-09-04T07:20:36Z ङघिञ 8448 ङघिञ moved page [[विभाग:वीकीपीःदीःयाः सोधनउपकारानि]] to [[विभाग:विकिपीडिया सोधनउपकारानि]]: Misspelled title 103788 wikitext text/x-wiki #REDIRECT [[:विभाग:विकिपीडिया सोधनउपकारानि]] 7tn2vhjozic6r0mxx5b76w1yxydfmx0 पटिरूप:Clickable button 10 7367 103789 2026-09-04T10:46:21Z 咽頭べさ 6149 Created page with "{{#invoke:Clickable button|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude>" 103789 wikitext text/x-wiki {{#invoke:Clickable button|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> p9tti49lmjq7ifp2faksbrk6uifwc4d 103795 103789 2026-09-04T10:56:56Z 咽頭べさ 6149 咽頭べさ moved page [[पटिरूप:Clickable button 2]] to [[पटिरूप:Clickable button]] 103789 wikitext text/x-wiki {{#invoke:Clickable button|main}}<noinclude> {{documentation}} <!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --> </noinclude> p9tti49lmjq7ifp2faksbrk6uifwc4d Module:Navbox/styles.css 828 7368 103790 2026-09-04T10:47:15Z 咽頭べさ 6149 Created page with "/* {{pp|small=y}} */ .navbox { box-sizing: border-box; border: 1px solid #a2a9b1; width: 100%; clear: both; font-size: 88%; text-align: center; padding: 1px; margin: 1em auto 0; /* Prevent preceding content from clinging to navboxes */ } .navbox .navbox { margin-top: 0; /* No top margin for nested navboxes */ } .navbox + .navbox-styles + .navbox, /* category positions are wrapped in an "empty" span in Parsoid [[phab:T378906]] */ .navbox + span.mw-empty-elt +..." 103790 sanitized-css text/css /* {{pp|small=y}} */ .navbox { box-sizing: border-box; border: 1px solid #a2a9b1; width: 100%; clear: both; font-size: 88%; text-align: center; padding: 1px; margin: 1em auto 0; /* Prevent preceding content from clinging to navboxes */ } .navbox .navbox { margin-top: 0; /* No top margin for nested navboxes */ } .navbox + .navbox-styles + .navbox, /* category positions are wrapped in an "empty" span in Parsoid [[phab:T378906]] */ .navbox + span.mw-empty-elt + .navbox-styles + .navbox { margin-top: -1px; /* Single pixel border between adjacent navboxes */ } .navbox-inner, .navbox-subgroup { width: 100%; } .navbox-group, .navbox-title, .navbox-abovebelow { padding: 0.25em 1em; line-height: 1.5em; text-align: center; } .navbox-group { white-space: nowrap; /* @noflip */ text-align: right; } .navbox, .navbox-subgroup { background-color: #fdfdfd; color:inherit; } .navbox-list { line-height: 1.5em; border-color: #fdfdfd; /* Must match background color */ } .navbox-list-with-group { text-align: left; border-left-width: 2px; border-left-style: solid; } /* cell spacing for navbox cells */ /* Borders above 2nd, 3rd, etc. rows */ /* TODO: figure out how to replace tr as structure; * with div structure it should be just a matter of first-child */ tr + tr > .navbox-abovebelow, tr + tr > .navbox-group, tr + tr > .navbox-image, tr + tr > .navbox-list { border-top: 2px solid #fdfdfd; /* Must match background color */ } .navbox-title { background-color: #ccf; /* Level 1 color */ color:inherit; } .navbox-abovebelow, .navbox-group, .navbox-subgroup .navbox-title { background-color: #ddf; /* Level 2 color */ color:inherit; } .navbox-subgroup .navbox-group, .navbox-subgroup .navbox-abovebelow { background-color: #e6e6ff; /* Level 3 color */ color:inherit; } .navbox-even { background-color: #f7f7f7; color:inherit; } .navbox-odd { background-color: transparent; color:inherit; } /* TODO: figure out how to remove reliance on td as structure */ .navbox .hlist td dl, .navbox .hlist td ol, .navbox .hlist td ul, .navbox td.hlist dl, .navbox td.hlist ol, .navbox td.hlist ul { padding: 0.125em 0; } .navbox .navbar { display: block; font-size: 100%; } .navbox-title .navbar { /* @noflip */ float: left; /* @noflip */ text-align: left; /* @noflip */ margin-right: 0.5em; } /** T367463 */ body.skin--responsive .navbox-image img { max-width: none !important; } @media print { body.ns-0 .navbox { display: none !important; } } ku94g873nj9xaasowc6yies69ls74c5 Module:Navbox 828 7369 103791 2026-09-04T10:48:41Z 咽頭べさ 6149 Created page with "require('strict') local p = {} local cfg = mw.loadData('Module:Navbox/configuration') local inArray = require("Module:TableTools").inArray local getArgs -- lazily initialized local hiding_templatestyles = {} -- global passthrough variables local passthrough = { [cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true, [cfg.arg.basestyle]=true, [cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true, [cfg.arg.bodyclass]=true, [cfg.a..." 103791 Scribunto text/plain require('strict') local p = {} local cfg = mw.loadData('Module:Navbox/configuration') local inArray = require("Module:TableTools").inArray local getArgs -- lazily initialized local hiding_templatestyles = {} -- global passthrough variables local passthrough = { [cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true, [cfg.arg.basestyle]=true, [cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true, [cfg.arg.bodyclass]=true, [cfg.arg.groupclass]=true, [cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true, [cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true, [cfg.arg.listclass]=true, [cfg.arg.name]=true, [cfg.arg.navbar]=true, [cfg.arg.state]=true, [cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true, argHash=true } -- helper functions local andnum = function(s, n) return string.format(cfg.arg[s .. '_and_num'], n) end local isblank = function(v) return (v or '') == '' end local function concatstrings(s) local r = table.concat(s, '') if r:match('^%s*$') then return nil end return r end local function concatstyles(s) local r = '' for _, v in ipairs(s) do v = mw.text.trim(v, "%s;") if not isblank(v) then r = r .. v .. ';' end end if isblank(r) then return nil end return r end local function getSubgroup(args, listnum, listText, prefix) local subArgs = { [cfg.arg.border] = cfg.keyword.border_subgroup, [cfg.arg.navbar] = cfg.keyword.navbar_plain, argHash = 0 } local hasSubArgs = false local subgroups_and_num = prefix and {prefix} or cfg.arg.subgroups_and_num for k, v in pairs(args) do k = tostring(k) for _, w in ipairs(subgroups_and_num) do w = string.format(w, listnum) .. "_" if (#k > #w) and (k:sub(1, #w) == w) then subArgs[k:sub(#w + 1)] = v hasSubArgs = true subArgs.argHash = subArgs.argHash + (v and #v or 0) end end end return hasSubArgs and p._navbox(subArgs) or listText end -- Main functions function p._navbox(args) if args.type == cfg.keyword.with_collapsible_groups then return p._withCollapsibleGroups(args) elseif args.type == cfg.keyword.with_columns then return p._withColumns(args) end local function striped(wikitext, border) -- Return wikitext with markers replaced for odd/even striping. -- Child (subgroup) navboxes are flagged with a category that is removed -- by parent navboxes. The result is that the category shows all pages -- where a child navbox is not contained in a parent navbox. local orphanCat = cfg.category.orphan if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then -- No change; striping occurs in outermost navbox. return wikitext .. orphanCat end local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part if args[cfg.arg.evenodd] then if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then first, second = second, first else first = args[cfg.arg.evenodd] second = first end end local changer if first == second then changer = first else local index = 0 changer = function (code) if code == '0' then -- Current occurrence is for a group before a nested table. -- Set it to first as a valid although pointless class. -- The next occurrence will be the first row after a title -- in a subgroup and will also be first. index = 0 return first end index = index + 1 return index % 2 == 1 and first or second end end local regex = orphanCat:gsub('([%[%]])', '%%%1') return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count end local function processItem(item, nowrapitems) if item:sub(1, 2) == '{|' then -- Applying nowrap to lines in a table does not make sense. -- Add newlines to compensate for trim of x in |parm=x in a template. return '\n' .. item .. '\n' end if nowrapitems == cfg.keyword.nowrapitems_yes then local lines = {} for line in (item .. '\n'):gmatch('([^\n]*)\n') do local prefix, content = line:match('^([*:;#]+)%s*(.*)') if prefix and not content:match(cfg.pattern.nowrap) then line = string.format(cfg.nowrap_item, prefix, content) end table.insert(lines, line) end item = table.concat(lines, '\n') end if item:match('^[*:;#]') then return '\n' .. item .. '\n' end return item end local function has_navbar() return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain and ( args[cfg.arg.name] or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '') ~= cfg.pattern.navbox ) end -- extract text color from css, which is the only permitted inline CSS for the navbar local function extract_color(css_str) -- return nil because navbar takes its argument into mw.html which handles -- nil gracefully, removing the associated style attribute return mw.ustring.match(';' .. css_str .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil end local function renderNavBar(titleCell) if has_navbar() then local navbar = require('Module:Navbar')._navbar titleCell:wikitext(navbar{ [cfg.navbar.name] = args[cfg.arg.name], [cfg.navbar.mini] = 1, [cfg.navbar.fontstyle] = extract_color( (args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '') ) }) end end local function renderTitleRow(tbl) if not args[cfg.arg.title] then return end local titleRow = tbl:tag('tr') local titleCell = titleRow:tag('th'):attr('scope', 'col') local titleColspan = 2 if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end if args[cfg.arg.image] then titleColspan = titleColspan + 1 end titleCell :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.titlestyle]) :addClass(cfg.class.navbox_title) :attr('colspan', titleColspan) renderNavBar(titleCell) titleCell :tag('div') -- id for aria-labelledby attribute :attr('id', mw.uri.anchorEncode(args[cfg.arg.title]) .. args.argHash) :addClass(args[cfg.arg.titleclass]) :css('font-size', '114%') :css('margin', '0 4em') :wikitext(processItem(args[cfg.arg.title])) end local function getAboveBelowColspan() local ret = 2 if args[cfg.arg.imageleft] then ret = ret + 1 end if args[cfg.arg.image] then ret = ret + 1 end return ret end local function renderAboveRow(tbl) if not args[cfg.arg.above] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.aboveclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.abovestyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') -- id for aria-labelledby attribute, if no title :attr('id', (not args[cfg.arg.title]) and (mw.uri.anchorEncode(args[cfg.arg.above]) .. args.argHash) or nil) :wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems])) end local function renderBelowRow(tbl) if not args[cfg.arg.below] then return end tbl:tag('tr') :tag('td') :addClass(cfg.class.navbox_abovebelow) :addClass(args[cfg.arg.belowclass]) :cssText(args[cfg.arg.basestyle]) :cssText(args[cfg.arg.belowstyle]) :attr('colspan', getAboveBelowColspan()) :tag('div') :wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems])) end local function renderListRow(tbl, index, listnum, listnums_size) local row = tbl:tag('tr') if index == 1 and args[cfg.arg.imageleft] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 2px 0 0') :cssText(args[cfg.arg.imageleftstyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.imageleft])) end local group_and_num = andnum('group', listnum) local groupstyle_and_num = andnum('groupstyle', listnum) if args[group_and_num] then local groupCell = row:tag('th') -- id for aria-labelledby attribute, if lone group with no title or above if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then groupCell :attr('id', mw.uri.anchorEncode(args[cfg.arg.group1]) .. args.argHash) end groupCell :attr('scope', 'row') :addClass(cfg.class.navbox_group) :addClass(args[cfg.arg.groupclass]) :cssText(args[cfg.arg.basestyle]) -- If groupwidth not specified, minimize width :css('width', args[cfg.arg.groupwidth] or '1%') groupCell :cssText(args[cfg.arg.groupstyle]) :cssText(args[groupstyle_and_num]) :wikitext(args[group_and_num]) end local listCell = row:tag('td') if args[group_and_num] then listCell :addClass(cfg.class.navbox_list_with_group) else listCell:attr('colspan', 2) end if not args[cfg.arg.groupwidth] then listCell:css('width', '100%') end local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing if index % 2 == 1 then rowstyle = args[cfg.arg.oddstyle] else rowstyle = args[cfg.arg.evenstyle] end local list_and_num = andnum('list', listnum) local listText = inArray(cfg.keyword.subgroups, args[list_and_num]) and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num] local oddEven = cfg.marker.oddeven if listText:sub(1, 12) == '</div><table' then -- Assume list text is for a subgroup navbox so no automatic striping for this row. oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part end local liststyle_and_num = andnum('liststyle', listnum) local listclass_and_num = andnum('listclass', listnum) listCell :css('padding', '0') :cssText(args[cfg.arg.liststyle]) :cssText(rowstyle) :cssText(args[liststyle_and_num]) :addClass(cfg.class.navbox_list) :addClass(cfg.class.navbox_part .. oddEven) :addClass(args[cfg.arg.listclass]) :addClass(args[listclass_and_num]) :tag('div') :css('padding', (index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em' ) :wikitext(processItem(listText, args[cfg.arg.nowrapitems])) if index == 1 and args[cfg.arg.image] then row :tag('td') :addClass(cfg.class.noviewer) :addClass(cfg.class.navbox_image) :addClass(args[cfg.arg.imageclass]) :css('width', '1px') -- Minimize width :css('padding', '0 0 0 2px') :cssText(args[cfg.arg.imagestyle]) :attr('rowspan', listnums_size) :tag('div') :wikitext(processItem(args[cfg.arg.image])) end end local function has_list_class(htmlclass) local patterns = { '^' .. htmlclass .. '$', '%s' .. htmlclass .. '$', '^' .. htmlclass .. '%s', '%s' .. htmlclass .. '%s' } for arg, _ in pairs(args) do if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then for _, pattern in ipairs(patterns) do if mw.ustring.find(args[arg] or '', pattern) then return true end end end end return false end -- there are a lot of list classes in the wild, so we add their TemplateStyles local function add_list_styles() local frame = mw.getCurrentFrame() local function add_list_templatestyles(htmlclass, templatestyles) if has_list_class(htmlclass) then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } else return '' end end local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles) local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles) -- a second workaround for [[phab:T303378]] -- when that issue is fixed, we can actually use has_navbar not to emit the -- tag here if we want if has_navbar() and hlist_styles == '' then hlist_styles = frame:extensionTag{ name = 'templatestyles', args = { src = cfg.hlist_templatestyles } } end -- hlist -> plainlist is best-effort to preserve old Common.css ordering. -- this ordering is not a guarantee because most navboxes will emit only -- one of these classes [hlist_note] return hlist_styles .. plainlist_styles end local function needsHorizontalLists(border) if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then return false end return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist) end local function hasBackgroundColors() for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('background', 1, true) then return true end end return false end local function hasBorders() for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do if tostring(args[key]):find('border', 1, true) then return true end end return false end local function isIllegible() local styleratio = require('Module:Color contrast')._styleratio for key, style in pairs(args) do if tostring(key):match(cfg.pattern.style) then if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then return true end end end return false end local function getTrackingCategories(border) local cats = {} if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end if isIllegible() then table.insert(cats, cfg.category.illegible) end if hasBorders() then table.insert(cats, cfg.category.borders) end return cats end local function renderTrackingCategories(builder, border) local title = mw.title.getCurrentTitle() if title.namespace ~= 10 then return end -- not in template space local subpage = title.subpageText if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox or subpage == cfg.keyword.subpage_testcases then return end for _, cat in ipairs(getTrackingCategories(border)) do builder:wikitext('[[Category:' .. cat .. ']]') end end local function renderMainTable(border, listnums) local tbl = mw.html.create('table') :addClass(cfg.class.nowraplinks) :addClass(args[cfg.arg.bodyclass]) local state = args[cfg.arg.state] if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then if state == cfg.keyword.state_collapsed then state = cfg.class.collapsed end tbl :addClass(cfg.class.collapsible) :addClass(state or cfg.class.autocollapse) end tbl:css('border-spacing', 0) if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then tbl :addClass(cfg.class.navbox_subgroup) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) else -- regular navbox - bodystyle and style will be applied to the wrapper table tbl :addClass(cfg.class.navbox_inner) :css('background', 'transparent') :css('color', 'inherit') end tbl:cssText(args[cfg.arg.innerstyle]) renderTitleRow(tbl) renderAboveRow(tbl) local listnums_size = #listnums for i, listnum in ipairs(listnums) do renderListRow(tbl, i, listnum, listnums_size) end renderBelowRow(tbl) return tbl end local function add_navbox_styles(hiding_templatestyles) local frame = mw.getCurrentFrame() -- This is a lambda so that it doesn't need the frame as a parameter local function add_user_styles(templatestyles) if not isblank(templatestyles) then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } end return '' end -- get templatestyles. load base from config so that Lua only needs to do -- the work once of parser tag expansion local base_templatestyles = cfg.templatestyles local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) -- The 'navbox-styles' div exists to wrap the styles to work around T200206 -- more elegantly. Instead of combinatorial rules, this ends up being linear -- number of CSS rules. return mw.html.create('div') :addClass(cfg.class.navbox_styles) :wikitext( add_list_styles() .. -- see [hlist_note] applied to 'before base_templatestyles' base_templatestyles .. templatestyles .. child_templatestyles .. table.concat(hiding_templatestyles) ) :done() end -- work around [[phab:T303378]] -- for each arg: find all the templatestyles strip markers, insert them into a -- table. then remove all templatestyles markers from the arg local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)' local argHash = 0 for k, arg in pairs(args) do if type(arg) == 'string' then for marker in string.gfind(arg, strip_marker_pattern) do table.insert(hiding_templatestyles, marker) end argHash = argHash + #arg args[k] = string.gsub(arg, strip_marker_pattern, '') end end if not args.argHash then args.argHash = argHash end local listnums = {} for k, _ in pairs(args) do if type(k) == 'string' then local listnum = k:match(cfg.pattern.listnum) if listnum and args[andnum('list', tonumber(listnum))] then table.insert(listnums, tonumber(listnum)) end end end table.sort(listnums) local border = mw.text.trim(args[cfg.arg.border] or args[1] or '') if border == cfg.keyword.border_child then border = cfg.keyword.border_subgroup end -- render the main body of the navbox local tbl = renderMainTable(border, listnums) local res = mw.html.create() -- render the appropriate wrapper for the navbox, based on the border param if border == cfg.keyword.border_none then res:node(add_navbox_styles(hiding_templatestyles)) local nav = res:tag('div') :attr('role', 'navigation') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode( args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1] ) .. args.argHash ) else nav:attr('aria-label', cfg.aria_label .. args.argHash) end elseif border == cfg.keyword.border_subgroup then -- We assume that this navbox is being rendered in a list cell of a -- parent navbox, and is therefore inside a div with padding:0em 0.25em. -- We start with a </div> to avoid the padding being applied, and at the -- end add a <div> to balance out the parent's </div> res :wikitext('</div>') :node(tbl) :wikitext('<div>') else res:node(add_navbox_styles(hiding_templatestyles)) local nav = res:tag('div') :attr('role', 'navigation') :addClass(cfg.class.navbox) :addClass(args[cfg.arg.navboxclass]) :cssText(args[cfg.arg.bodystyle]) :cssText(args[cfg.arg.style]) :css('padding', '3px') :node(tbl) -- aria-labelledby title, otherwise above, otherwise lone group if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then nav:attr( 'aria-labelledby', mw.uri.anchorEncode( args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1] ) .. args.argHash ) else nav:attr('aria-label', cfg.aria_label .. args.argHash) end end if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then renderTrackingCategories(res, border) end return striped(tostring(res), border) end --p._navbox function p._withCollapsibleGroups(pargs) -- table for args passed to navbox local targs = {} -- process args local passthroughLocal = { [cfg.arg.bodystyle] = true, [cfg.arg.border] = true, [cfg.arg.style] = true, } for k,v in pairs(pargs) do if k and type(k) == 'string' then if passthrough[k] or passthroughLocal[k] then targs[k] = v elseif (k:match(cfg.pattern.num)) then local n = k:match(cfg.pattern.num) local list_and_num = andnum('list', n) if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum)) and targs[list_and_num] == nil and pargs[andnum('group', n)] == nil and pargs[andnum('sect', n)] == nil and pargs[andnum('section', n)] == nil) then targs[list_and_num] = concatstrings({ pargs[list_and_num] or '', pargs[andnum('content', n)] or '' }) if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num]) end elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum)) and targs[list_and_num] == nil) then local titlestyle = concatstyles({ pargs[cfg.arg.groupstyle] or '', pargs[cfg.arg.secttitlestyle] or '', pargs[andnum('groupstyle', n)] or '', pargs[andnum('sectiontitlestyle', n)] or '' }) local liststyle = concatstyles({ pargs[cfg.arg.liststyle] or '', pargs[cfg.arg.contentstyle] or '', pargs[andnum('liststyle', n)] or '', pargs[andnum('contentstyle', n)] or '' }) local title = concatstrings({ pargs[andnum('group', n)] or '', pargs[andnum('sect', n)] or '', pargs[andnum('section', n)] or '' }) local list = concatstrings({ pargs[list_and_num] or '', pargs[andnum('content', n)] or '' }) if list and inArray(cfg.keyword.subgroups, list) then list = getSubgroup(pargs, n, list) end local abbr_and_num = andnum('abbr', n) local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected]) and cfg.keyword.state_uncollapsed or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed) targs[list_and_num] =p._navbox({ cfg.keyword.border_child, [cfg.arg.navbar] = cfg.keyword.navbar_plain, [cfg.arg.state] = state, [cfg.arg.basestyle] = pargs[cfg.arg.basestyle], [cfg.arg.title] = title, [cfg.arg.titlestyle] = titlestyle, [andnum('list', 1)] = list, [cfg.arg.liststyle] = liststyle, [cfg.arg.listclass] = pargs[andnum('listclass', n)], [cfg.arg.image] = pargs[andnum('image', n)], [cfg.arg.imageleft] = pargs[andnum('imageleft', n)], [cfg.arg.listpadding] = pargs[cfg.arg.listpadding], argHash = pargs.argHash }) end end end end -- ordering of style and bodystyle targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''}) targs[cfg.arg.bodystyle] = nil -- child or subgroup if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end return p._navbox(targs) end --p._withCollapsibleGroups function p._withColumns(pargs) -- table for args passed to navbox local targs = {} -- tables of column numbers local colheadernums = {} local colnums = {} local colfooternums = {} -- process args local passthroughLocal = { [cfg.arg.evenstyle]=true, [cfg.arg.groupstyle]=true, [cfg.arg.liststyle]=true, [cfg.arg.oddstyle]=true, [cfg.arg.state]=true, } for k,v in pairs(pargs) do if passthrough[k] or passthroughLocal[k] then targs[k] = v elseif type(k) == 'string' then if k:match(cfg.pattern.listnum) then local n = k:match(cfg.pattern.listnum) targs[andnum('liststyle', n + 2)] = pargs[andnum('liststyle', n)] targs[andnum('group', n + 2)] = pargs[andnum('group', n)] targs[andnum('groupstyle', n + 2)] = pargs[andnum('groupstyle', n)] if v and inArray(cfg.keyword.subgroups, v) then targs[andnum('list', n + 2)] = getSubgroup(pargs, n, v) else targs[andnum('list', n + 2)] = v end elseif (k:match(cfg.pattern.colheadernum) and v ~= '') then table.insert(colheadernums, tonumber(k:match(cfg.pattern.colheadernum))) elseif (k:match(cfg.pattern.colnum) and v ~= '') then table.insert(colnums, tonumber(k:match(cfg.pattern.colnum))) elseif (k:match(cfg.pattern.colfooternum) and v ~= '') then table.insert(colfooternums, tonumber(k:match(cfg.pattern.colfooternum))) end end end table.sort(colheadernums) table.sort(colnums) table.sort(colfooternums) -- HTML table for list1 local coltable = mw.html.create( 'table' ):addClass('navbox-columns-table') local row, col local tablestyle = ( (#colheadernums > 0) or (not isblank(pargs[cfg.arg.fullwidth])) ) and 'width:100%' or 'width:auto; margin-left:auto; margin-right:auto' coltable:cssText(concatstyles({ 'border-spacing: 0px; text-align:left', tablestyle, pargs[cfg.arg.coltablestyle] or '' })) --- Header row --- if (#colheadernums > 0) then row = coltable:tag('tr') for k, n in ipairs(colheadernums) do col = row:tag('th'):addClass('navbox-abovebelow') col:cssText(concatstyles({ (k > 1) and 'border-left:2px solid #fdfdfd' or '', 'font-weight:bold', pargs[cfg.arg.colheaderstyle] or '', pargs[andnum('colheaderstyle', n)] or '' })) col:attr('colspan', tonumber(pargs[andnum('colheadercolspan', n)])) col:wikitext(pargs[andnum('colheader', n)]) end end --- Main columns --- row = coltable:tag('tr'):css('vertical-align', 'top') for k, n in ipairs(colnums) do if k == 1 and isblank(pargs[andnum('colheader', 1)]) and isblank(pargs[andnum('colfooter', 1)]) and isblank(pargs[cfg.arg.fullwidth]) then local nopad = inArray( {'off', '0', '0em', '0px'}, mw.ustring.gsub(pargs[cfg.arg.padding] or '', '[;%%]', '')) if not nopad then row:tag('td'):wikitext('&nbsp;&nbsp;&nbsp;') :css('width', (pargs[cfg.arg.padding] or '5em')) end end col = row:tag('td'):addClass('navbox-list') col:cssText(concatstyles({ (k > 1) and 'border-left:2px solid #fdfdfd' or '', 'padding:0px', pargs[cfg.arg.colstyle] or '', ((n%2 == 0) and pargs[cfg.arg.evencolstyle] or pargs[cfg.arg.oddcolstyle]) or '', pargs[andnum('colstyle', n)] or '', 'width:' .. (pargs[andnum('colwidth', n)] or pargs[cfg.arg.colwidth] or '10em') })) local wt = pargs[andnum('col', n)] if wt and inArray(cfg.keyword.subgroups, wt) then wt = getSubgroup(pargs, n, wt, cfg.arg.col_and_num) end col:tag('div'):newline():wikitext(wt):newline() end --- Footer row --- if (#colfooternums > 0) then row = coltable:tag('tr') for k, n in ipairs(colfooternums) do col = row:tag('td'):addClass('navbox-abovebelow') col:cssText(concatstyles({ (k > 1) and 'border-left:2px solid #fdfdfd' or '', 'font-weight:bold', pargs[cfg.arg.colfooterstyle] or '', pargs[andnum('colfooterstyle', n)] or '' })) col:attr('colspan', tonumber(pargs[andnum('colfootercolspan', n)])) col:wikitext(pargs[andnum('colfooter', n)]) end end -- assign table to list1 targs[andnum('list', 1)] = tostring(coltable) if isblank(pargs[andnum('colheader', 1)]) and isblank(pargs[andnum('col', 1)]) and isblank(pargs[andnum('colfooter', 1)]) then targs[andnum('list', 1)] = targs[andnum('list', 1)] .. cfg.category.without_first_col end -- Other parameters targs[cfg.arg.border] = pargs[cfg.arg.border] or pargs[1] targs[cfg.arg.evenodd] = (not isblank(pargs[cfg.arg.evenodd])) and pargs[cfg.arg.evenodd] or nil targs[cfg.arg.list1padding] = '0px' targs[andnum('liststyle', 1)] = 'background:transparent;color:inherit;' targs[cfg.arg.style] = concatstyles({pargs[cfg.arg.style], pargs[cfg.arg.bodystyle]}) targs[cfg.arg.tracking] = 'no' return p._navbox(targs) end --p._withColumns -- Template entry points function p.navbox (frame, boxtype) local function readArgs(args, prefix) local function readSubgroups(element, i) if inArray(cfg.keyword.subgroups, args[prefix .. andnum(element, i)]) then for _, v in ipairs(cfg.arg.subgroups_and_num) do readArgs(args, prefix .. string.format(v, i) .. "_") end readArgs(args, prefix .. andnum('col', i) .. "_") end end -- Read the arguments in the order they'll be output in, to make references -- number in the right order. local _ _ = args[prefix .. cfg.arg.title] _ = args[prefix .. cfg.arg.above] -- Limit this to 20 as covering 'most' cases (that's a SWAG) and because -- iterator approach won't work here local boxtype = args.type or cfg.keyword[boxtype] if boxtype == cfg.keyword.with_columns then for i = 1, 20 do _ = args[prefix .. andnum('colheader', i)] end for i = 1, 20 do readSubgroups('col', i) end for i = 1, 20 do _ = args[prefix .. andnum('colfooter', i)] end end for i = 1, 20 do _ = args[prefix .. andnum('group', i)] readSubgroups('list', i) end _ = args[prefix .. cfg.arg.below] end if not getArgs then getArgs = require('Module:Arguments').getArgs end local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}}) readArgs(args, "") args.argHash = nil -- we shouldn't accept argHash passed from a template args.type = args.type or cfg.keyword[boxtype] return p['_navbox'](args) end p[cfg.keyword.with_collapsible_groups] = function (frame) return p.navbox(frame, 'with_collapsible_groups') end p[cfg.keyword.with_columns] = function (frame) return p.navbox(frame, 'with_columns') end return p 1s4hl193ornydh8zrrhga8nr1v6arn9 Module:Navbox/configuration 828 7370 103792 2026-09-04T10:50:05Z 咽頭べさ 6149 Created page with "return { aria_label = 'Navbox', nowrap_item = '%s<span class="nowrap">%s</span>', templatestyles = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' } }, hlist_templatestyles = 'Hlist/styles.css', plainlist_templatestyles = 'Plainlist/styles.css', -- do not localize marker table marker = { oddeven = '\127_ODDEVEN_\127', restart = '\127_ODDEVEN0_\127', regex = '\127_ODDEVEN(%d?)_\127' }, category = {..." 103792 Scribunto text/plain return { aria_label = 'Navbox', nowrap_item = '%s<span class="nowrap">%s</span>', templatestyles = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' } }, hlist_templatestyles = 'Hlist/styles.css', plainlist_templatestyles = 'Plainlist/styles.css', -- do not localize marker table marker = { oddeven = '\127_ODDEVEN_\127', restart = '\127_ODDEVEN0_\127', regex = '\127_ODDEVEN(%d?)_\127' }, category = { orphan = '[[Category:Navbox orphans]]', horizontal_lists = 'Navigational boxes without horizontal lists', background_colors = 'Navboxes using background colours', illegible = 'Potentially illegible navboxes', borders = 'Navboxes using borders', without_first_col = '[[Category:Pages using navbox columns without the first column]]' }, keyword = { border_subgroup = 'subgroup', border_child = 'child', border_none = 'none', evenodd_swap = 'swap', navbar_off = 'off', navbar_plain = 'plain', nocat_false = 'false', nowrapitems_yes = 'yes', orphan_yes = 'yes', state_collapsed = 'collapsed', state_off = 'off', state_plain = 'plain', state_uncollapsed = 'uncollapsed', subgroups = {'subgroup', 'child', ''}, subpage_doc = 'doc', subpage_sandbox = 'sandbox', subpage_testcases = 'testcases', tracking_no = 'no', with_collapsible_groups = 'with collapsible groups', with_collapsible_groups_short = 'collapsible', with_columns = 'with columns', with_columns_short = 'columns', }, class = { autocollapse = 'autocollapse', collapsible = 'mw-collapsible', collapsed = 'mw-collapsed', -- Warning navbox = 'navbox', -- WMF currently hides 'navbox' from mobile, -- so you probably shouldn't change the navbox class. navbox_abovebelow = 'navbox-abovebelow', navbox_group = 'navbox-group', navbox_image = 'navbox-image', navbox_inner = 'navbox-inner', navbox_list = 'navbox-list', navbox_list_with_group = 'navbox-list-with-group', navbox_part = 'navbox-', -- do not l10n navbox_styles = 'navbox-styles', navbox_subgroup = 'navbox-subgroup', navbox_title = 'navbox-title', -- l10n only if you change pattern.navbox_title below navbox_odd_part = 'odd', -- do not l10n navbox_even_part = 'even', -- do not l10n nomobile = 'nomobile', nowraplinks = 'nowraplinks', noviewer = 'noviewer', -- used to remove images from MediaViewer notheme = 'notheme' }, pattern = { class = 'class', colnum = '^col(%d+)$', colheadernum = '^col(%d+)header$', colfooternum = '^col(%d+)footer$', contentnum = '^content(%d+)$', groupnum = '^group(%d+)$', hlist = 'hlist', listnum = '^list(%d+)$', navbox = 'Template:Navbox', navbox_title = '<th[^>]*"navbox%-title"', nowrap = '^<span class="nowrap">', num = '^%a+(%d+)$', plainlist = 'plainlist', sandbox = '/sandbox$', sectionnum = '^section(%d+)$', sectnum = '^sect(%d+)$', style = 'style$', with_collapsible_groups = 'Template:Navbox with collapsible groups', with_columns = 'Template:Navbox with columns', }, arg = { abbr_and_num = 'abbr%d', above = 'above', aboveclass = 'aboveclass', abovestyle = 'abovestyle', basestyle = 'basestyle', below = 'below', belowclass = 'belowclass', belowstyle = 'belowstyle', bodyclass = 'bodyclass', bodystyle = 'bodystyle', border = 'border', content_and_num = 'content%d', contentstyle = 'contentstyle', contentstyle_and_num = 'content%dstyle', colheaderstyle = 'colheaderstyle', colheader_and_num = 'col%dheader', colheaderstyle_and_num = 'col%dheaderstyle', colheadercolspan_and_num = 'col%dheadercolspan', colstyle = 'colstyle', col_and_num = 'col%d', colstyle_and_num = 'col%dstyle', colwidth = 'colwidth', colwidth_and_num = 'col%dwidth', colfooterstyle = 'colfooterstyle', colfooter_and_num = 'col%dfooter', colfooterstyle_and_num = 'col%dfooterstyle', colfootercolspan_and_num = 'col%dfootercolspan', coltablestyle = 'coltablestyle', evencolstyle = 'evencolstyle', evenodd = 'evenodd', evenstyle = 'evenstyle', fullwidth = 'fullwidth', group1 = 'group1', group2 = 'group2', group_and_num = 'group%d', groupclass = 'groupclass', groupstyle = 'groupstyle', groupstyle_and_num = 'group%dstyle', groupwidth = 'groupwidth', image = 'image', image_and_num = 'image%d', imageclass = 'imageclass', imageleft = 'imageleft', imageleft_and_num = 'imageleft%d', imageleftstyle = 'imageleftstyle', imagestyle = 'imagestyle', innerstyle = 'innerstyle', list1padding = 'list1padding', list_and_num = 'list%d', listclass = 'listclass', listclass_and_num = 'list%dclass', listpadding = 'listpadding', liststyle = 'liststyle', liststyle_and_num = 'list%dstyle', name = 'name', navbar = 'navbar', navboxclass = 'navboxclass', nocat = 'nocat', nowrapitems = 'nowrapitems', oddcolstyle = 'oddcolstyle', oddstyle = 'oddstyle', orphan = 'orphan', padding = 'padding', sect_and_num = 'sect%d', section_and_num = 'section%d', sectiontitlestyle_and_num = 'section%dtitlestyle', secttitlestyle = 'secttitlestyle', selected = 'selected', state = 'state', state_and_num = 'state%d', style = 'style', subgroups_and_num = {'subgroup%d', 'child%d', '%d'}, templatestyles = 'templatestyles', child_templatestyles = 'child templatestyles', title = 'title', titleclass = 'titleclass', titlestyle = 'titlestyle', tracking = 'tracking', }, -- names of navbar arguments navbar = { name = 1, fontstyle = 'fontstyle', mini = 'mini' } } hfe9tuviwm23frg4eyuetl5fcr6lsto Module:Clickable button 828 7371 103793 2026-09-04T10:51:59Z 咽頭べさ 6149 Created page with "-- This module implements {{clickable button 2}}. local yesno = require('Module:Yesno') local delink = require('Module:Delink')._delink local p = {} function p.main(frame) local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame) return p._main(args) end function p._main(args) -- If first arg or a url is not provided, -- but we have a second arg, make a button. -- Otherwise, return nothing. args.originalInput = args[1] args[1] = delink({..." 103793 Scribunto text/plain -- This module implements {{clickable button 2}}. local yesno = require('Module:Yesno') local delink = require('Module:Delink')._delink local p = {} function p.main(frame) local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame) return p._main(args) end function p._main(args) -- If first arg or a url is not provided, -- but we have a second arg, make a button. -- Otherwise, return nothing. args.originalInput = args[1] args[1] = delink({args[1]}) if args[1] == "" then args[1] = nil end if not args[1] and not args.url then if args[2] then p.nolink = true else return '' end end local data = p.makeLinkData(args) local link = p.renderLink(args.originalInput, data) local trackingCategories = p.renderTrackingCategories(args) return link .. trackingCategories end function p.makeLinkData(args) local data = {} -- Get the link and display values, -- and find whether we are outputting -- a wikilink or a URL. if args.url then data.isUrl = true data.link = args.url if args[1] then data.display = args[1] elseif args[2] then data.display = args[2] else data.display = args.url p.urlisdisplay = true end else data.isUrl = false p.urlisdisplay = false data.link = args[1] if args[2] then data.display = args[2] else data.display = args[1] end if args[1] and args[1]:find('http') then data.isUrl = true end end if yesno(args.link) == false then p.nolink = true end -- Colours -- For the merge with {{clickable button}} local colour = args.color and args.color:lower() -- Classes local class = args.class and args.class:lower() data.classes = {} if class == 'ui-button-green' or class == 'ui-button-blue' or class == 'ui-button-red' then table.insert( data.classes, 'submit ui-button ui-widget ui-state-default ui-corner-all' .. ' ui-button-text-only ui-button-text' ) else table.insert(data.classes, 'mw-ui-button') end --If class is unset, --then let color determine class if not class then if colour == 'blue' then class = 'mw-ui-progressive' elseif colour == 'red' then class = 'mw-ui-destructive' elseif colour == 'green' then class = 'mw-ui-constructive' end end if class then table.insert(data.classes, class) end -- Styles do --[[ -- Check whether we are on the same page as we have specified in -- args[1], but not if we are using a URL link, as then args[1] is only -- a display value. If we are currently on the page specified in -- args[1] make the button colour darker so that it stands out from -- other buttons on the page. --]] local success, linkTitle, currentTitle if not data.isUrl then currentTitle = mw.title.getCurrentTitle() success, linkTitle = pcall(mw.title.new, args[1]) elseif p.urlisdisplay then currentTitle = mw.title.getCurrentTitle() end if success and linkTitle and mw.title.equals(currentTitle, linkTitle) and not p.urlisdisplay then if class == 'ui-button-blue' or class == 'mw-ui-progressive' or class == 'mw-ui-constructive' then data.backgroundColor = '#2962CB' data.color = '#fff' elseif class == 'ui-button-green' then data.backgroundColor = '#008B6D' elseif class == 'ui-button-red' or class == 'mw-ui-destructive' then data.backgroundColor = '#A6170F' else data.backgroundColor = '#CCC' data.color = '#666' end elseif p.urlisdisplay then data.dummyLink = tostring(currentTitle) end -- Add user-specified styles. data.style = args.style end return data end function p.renderLink(originalInput, data) -- Render the display span tag. local display do local displaySpan = mw.html.create('span') for i, class in ipairs(data.classes or {}) do displaySpan:addClass(class) end displaySpan :css{ ['background-color'] = data.backgroundColor, color = data.color } if data.style then displaySpan:cssText(data.style) end displaySpan:wikitext(data.display) display = tostring(displaySpan) end -- Render the link local link if originalInput and originalInput:find('|') then link = string.format('[[%s|%s]]', delink({originalInput, wikilinks = 'target'}), display) elseif p.nolink then if p.urlisdisplay then link = string.format('[[%s|%s]]', data.dummyLink, display) else link = string.format('%s', display) end else if data.isUrl then link = string.format('[%s %s]', data.link, display) else link = string.format('[[%s |%s]]', data.link, display) end end return string.format('<span class="plainlinks clickbutton">%s</span>', link) end function p.renderTrackingCategories(args) if yesno(args.category) == false then return '' end local class = args.class and args.class:lower() if class == 'ui-button-green' or class == 'ui-button-blue' or class == 'ui-button-red' then return '[[Category:Pages using old style ui-button-color]]' else return '' end end return p 2y4zqg2drz0jqpm59tyakc7koi33ehg Module:Delink 828 7372 103794 2026-09-04T10:55:10Z 咽頭べさ 6149 Created page with "-- This module de-links most wikitext. require("strict") local p = {} local getArgs local function delinkReversePipeTrick(s) if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes. return s end return s:match("%[%[|(.*)%]%]") end local function delinkPipeTrick(s) -- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]]. -- First, remove the text before the first colon, if any. if s:match(":") then s = s:match("%[%[.-..." 103794 Scribunto text/plain -- This module de-links most wikitext. require("strict") local p = {} local getArgs local function delinkReversePipeTrick(s) if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes. return s end return s:match("%[%[|(.*)%]%]") end local function delinkPipeTrick(s) -- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]]. -- First, remove the text before the first colon, if any. if s:match(":") then s = s:match("%[%[.-:(.*)|%]%]") -- If there are no colons, grab all of the text apart from the square brackets and the pipe. else s = s:match("%[%[(.*)|%]%]") end -- Next up, brackets and commas. if s:match("%(.-%)$") then -- Brackets trump commas. s = s:match("(.-) ?%(.-%)$") elseif s:match(",") then -- If there are no brackets, display only the text before the first comma. s = s:match("(.-),.*$") end return s end -- Return wikilink target |wikilinks=target local function getDelinkedTarget(s) local result = s -- Deal with the reverse pipe trick. if result:match("%[%[|") then return delinkReversePipeTrick(result) end result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs. result = mw.text.decode(result, true) -- decode HTML entities. -- Check for bad titles. To do this we need to find the -- title area of the link, i.e. the part before any pipes. local target_area if result:match("|") then -- Find if we're dealing with a piped link. target_area = result:match("^%[%[(.-)|.*%]%]") else target_area = result:match("^%[%[(.-)%]%]") end -- Check for bad characters. if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then return s end return target_area end local function getDelinkedLabel(s) local result = s -- Deal with the reverse pipe trick. if result:match("%[%[|") then return delinkReversePipeTrick(result) end result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs. result = mw.text.decode(result, true) -- decode HTML entities. -- Check for bad titles. To do this we need to find the -- title area of the link, i.e. the part before any pipes. local target_area if result:match("|") then -- Find if we're dealing with a piped link. target_area = result:match("^%[%[(.-)|.*%]%]") else target_area = result:match("^%[%[(.-)%]%]") end -- Check for bad characters. if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then return s end -- Check for categories, interwikis, and files. local colon_prefix = result:match("%[%[(.-):.*%]%]") or "" -- Get the text before the first colon. local ns = mw.site.namespaces[colon_prefix] -- see if this is a known namespace if mw.language.isKnownLanguageTag(colon_prefix) or (ns and (ns.canonicalName == "File" or ns.canonicalName == "Category")) then return "" end -- Remove the colon if the link is using the [[Help:Colon trick]]. if result:match("%[%[:") then result = "[[" .. result:match("%[%[:(.*%]%])") end -- Deal with links using the [[Help:Pipe trick]]. if mw.ustring.match(result, "^%[%[[^|]*|%]%]") then return delinkPipeTrick(result) end -- Find the display area of the wikilink if result:match("|") then -- Find if we're dealing with a piped link. result = result:match("^%[%[.-|(.+)%]%]") -- Remove new lines from the display of multiline piped links, -- where the pipe is before the first new line. result = result:gsub("\n", "") else result = result:match("^%[%[(.-)%]%]") end return result end local function delinkURL(s) -- Assume we have already delinked internal wikilinks, and that -- we have been passed some text between two square brackets [foo]. -- If the text contains a line break it is not formatted as a URL, regardless of other content. if s:match("\n") then return s end -- Check if the text has a valid URL prefix and at least one valid URL character. local valid_url_prefixes = {"//", "http://", "https://", "ftp://", "gopher://", "mailto:", "news:", "irc://"} local url_prefix for _ ,v in ipairs(valid_url_prefixes) do if mw.ustring.match(s, '^%[' .. v ..'[^"%s].*%]' ) then url_prefix = v break end end -- Get display text if not url_prefix then return s end s = s:match("^%[" .. url_prefix .. "(.*)%]") -- Grab all of the text after the URL prefix and before the final square bracket. s = s:match('^.-(["<> ].*)') or "" -- Grab all of the text after the first URL separator character ("<> ). s = mw.ustring.match(s, "^%s*(%S.*)$") or "" -- If the separating character was a space, trim it off. local s_decoded = mw.text.decode(s, true) if mw.ustring.match(s_decoded, "%c") then return s end return s_decoded end local function delinkLinkClass(text, pattern, delinkFunction) if type(text) ~= "string" then error("Attempt to de-link non-string input.", 2) end if type(pattern) ~= "string" or mw.ustring.sub(pattern, 1, 1) ~= "^" then error('Invalid pattern detected. Patterns must begin with "^".', 2) end -- Iterate over the text string, and replace any matched text. using the -- delink function. We need to iterate character by character rather -- than just use gsub, otherwise nested links aren't detected properly. local result = "" while text ~= "" do -- Replace text using one iteration of gsub. text = mw.ustring.gsub(text, pattern, delinkFunction, 1) -- Append the left-most character to the result string. result = result .. mw.ustring.sub(text, 1, 1) text = mw.ustring.sub(text, 2, -1) end return result end function p._delink(args) local text = args[1] or "" if args.refs == "yes" then -- Remove any [[Help:Strip markers]] representing ref tags. In most situations -- this is not a good idea - only use it if you know what you are doing! text = mw.ustring.gsub(text, "UNIQ%w*%-ref%-%d*%-QINU", "") end if args.comments ~= "no" then text = text:gsub("<!%-%-.-%-%->", "") -- Remove html comments. end if args.wikilinks ~= "no" and args.wikilinks ~= "target" then -- De-link wikilinks and return the label portion of the wikilink. text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedLabel) elseif args.wikilinks == "target" then -- De-link wikilinks and return the target portions of the wikilink. text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedTarget) end if args.urls ~= "no" then text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs. end if args.whitespace ~= "no" then -- Replace single new lines with a single space, but leave double new lines -- and new lines only containing spaces or tabs before a second new line. text = mw.ustring.gsub(text, "([^\n \t][ \t]*)\n([ \t]*[^\n \t])", "%1 %2") text = text:gsub("[ \t]+", " ") -- Remove extra tabs and spaces. end return text end function p.delink(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end return p._delink(getArgs(frame, {wrappers = 'Template:Delink'})) end return p ap0hgbdtouyp0g9x21nujuwhyky0459 पटिरूप:Clickable button 2 10 7373 103796 2026-09-04T10:56:56Z 咽頭べさ 6149 咽頭べさ moved page [[पटिरूप:Clickable button 2]] to [[पटिरूप:Clickable button]] 103796 wikitext text/x-wiki #REDIRECT [[पटिरूप:Clickable button]] tukfqobletpi7jnwomb73zn4kuyioqw