Wikisumber
mswikisource
https://ms.wikisource.org/wiki/Laman_Utama
MediaWiki 1.46.0-wmf.23
first-letter
Media
Khas
Perbincangan
Pengguna
Perbincangan pengguna
Wikisumber
Perbincangan Wikisumber
Fail
Perbincangan fail
MediaWiki
Perbincangan MediaWiki
Templat
Perbincangan templat
Bantuan
Perbincangan bantuan
Kategori
Perbincangan kategori
Gerbang
Perbincangan gerbang
Pengarang
Perbincangan pengarang
Karya
Perbincangan karya
Terjemahan
Perbincangan terjemahan
Laman
Perbincangan laman
Indeks
Perbincangan indeks
TimedText
TimedText talk
Modul
Perbincangan modul
Acara
Perbincangan acara
Modul:Arguments
828
986
22790
16216
2026-04-14T13:22:32Z
Hakimi97
9
Dilindungi "[[Modul:Arguments]]": Laman berimpak tinggi ([Sunting=Benarkan penyelia sahaja] (tak terbatas) [Pindahkan=Benarkan penyelia sahaja] (tak terbatas))
16215
Scribunto
text/plain
--[=[
This module provides easy processing of arguments passed to Scribunto from #invoke.
It is intended for use by other Lua modules, and should not be called from #invoke directly.
]=]
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local arguments = {}
-- Generate four different tidyVal functions, so that we don't have to check the options every time we call it.
local function tidyValDefault(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
else
return val
end
else
return val
end
end
local function tidyValTrimOnly(key, val)
if type(val) == 'string' then
return val:match('^%s*(.-)%s*$')
else
return val
end
end
local function tidyValRemoveBlanksOnly(key, val)
if type(val) == 'string' then
if val:find('%S') then
return val
else
return nil
end
else
return val
end
end
local function tidyValNoChange(key, val)
return val
end
local function matchesTitle(given, title)
local tp = type( given )
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
end
local translate_mt = { __index = function(t, k) return k end }
function arguments.getArgs(frame, options)
checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}
--[[
-- Set up argument translation.
--]]
options.translate = options.translate or {}
if getmetatable(options.translate) == nil then
setmetatable(options.translate, translate_mt)
end
if options.backtranslate == nil then
options.backtranslate = {}
for k,v in pairs(options.translate) do
options.backtranslate[v] = k
end
end
if options.backtranslate and getmetatable(options.backtranslate) == nil then
setmetatable(options.backtranslate, {
__index = function(t, k)
if options.translate[k] ~= k then
return nil
else
return k
end
end
})
end
--[[
-- Get the argument tables. If we were passed a valid frame object, get the
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
-- on the options set and on the parent frame's availability. If we weren't
-- passed a valid frame object, we are being called from another Lua module
-- or from the debug console, so assume that we were passed a table of args
-- directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
if options.wrappers then
--[[
-- The wrappers option makes Module:Arguments look up arguments in
-- either the frame argument table or the parent argument table, but
-- not both. This means that users can use either the #invoke syntax
-- or a wrapper template without the loss of performance associated
-- with looking arguments up in both the frame and the parent frame.
-- Module:Arguments will look up arguments in the parent frame
-- if it finds the parent frame's title in options.wrapper;
-- otherwise it will look up arguments in the frame object passed
-- to getArgs.
--]]
local parent = frame:getParent()
if not parent then
fargs = frame.args
else
local title = parent:getTitle():gsub('/sandbox$', '')
local found = false
if matchesTitle(options.wrappers, title) then
found = true
elseif type(options.wrappers) == 'table' then
for _,v in pairs(options.wrappers) do
if matchesTitle(v, title) then
found = true
break
end
end
end
-- We test for false specifically here so that nil (the default) acts like true.
if found or options.frameOnly == false then
pargs = parent.args
end
if not found or options.parentOnly == false then
fargs = frame.args
end
end
else
-- options.wrapper isn't set, so check the other options.
if not options.parentOnly then
fargs = frame.args
end
if not options.frameOnly then
local parent = frame:getParent()
pargs = parent and parent.args or nil
end
end
if options.parentFirst then
fargs, pargs = pargs, fargs
end
else
luaArgs = frame
end
-- Set the order of precedence of the argument tables. If the variables are
-- nil, nothing will be added to the table, which is how we avoid clashes
-- between the frame/parent args and the Lua args.
local argTables = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs
--[[
-- Generate the tidyVal function. If it has been specified by the user, we
-- use that; if not, we choose one of four functions depending on the
-- options chosen. This is so that we don't have to call the options table
-- every time the function is called.
--]]
local tidyVal = options.valueFunc
if tidyVal then
if type(tidyVal) ~= 'function' then
error(
"bad value assigned to option 'valueFunc'"
.. '(function expected, got '
.. type(tidyVal)
.. ')',
2
)
end
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end
--[[
-- Set up the args, metaArgs and nilArgs tables. args will be the one
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
-- arguments are memoized in nilArgs, and the metatable connects all of them
-- together.
--]]
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
setmetatable(args, metatable)
local function mergeArgs(tables)
--[[
-- Accepts multiple tables as input and merges their keys and values
-- into one table. If a value is already present it is not overwritten;
-- tables listed earlier have precedence. We are also memoizing nil
-- values, which can be overwritten if they are 's' (soft).
--]]
for _, t in ipairs(tables) do
for key, val in pairs(t) do
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
local tidiedVal = tidyVal(key, val)
if tidiedVal == nil then
nilArgs[key] = 's'
else
metaArgs[key] = tidiedVal
end
end
end
end
end
--[[
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
-- and are only fetched from the argument tables once. Fetching arguments
-- from the argument tables is the most resource-intensive step in this
-- module, so we try and avoid it where possible. For this reason, nil
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
-- in the metatable of when pairs and ipairs have been called, so we do not
-- run pairs and ipairs on the argument tables more than once. We also do
-- not run ipairs on fargs and pargs if pairs has already been run, as all
-- the arguments will already have been copied over.
--]]
metatable.__index = function (t, key)
--[[
-- Fetches an argument when the args table is indexed. First we check
-- to see if the value is memoized, and if not we try and fetch it from
-- the argument tables. When we check memoization, we need to check
-- metaArgs before nilArgs, as both can be non-nil at the same time.
-- If the argument is not present in metaArgs, we also check whether
-- pairs has been run yet. If pairs has already been run, we return nil.
-- This is because all the arguments will have already been copied into
-- metaArgs by the mergeArgs function, meaning that any other arguments
-- must be nil.
--]]
if type(key) == 'string' then
key = options.translate[key]
end
local val = metaArgs[key]
if val ~= nil then
return val
elseif metatable.donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs(argTables) do
local argTableVal = tidyVal(key, argTable[key])
if argTableVal ~= nil then
metaArgs[key] = argTableVal
return argTableVal
end
end
nilArgs[key] = 'h'
return nil
end
metatable.__newindex = function (t, key, val)
-- This function is called when a module tries to add a new value to the
-- args table, or tries to change an existing value.
if type(key) == 'string' then
key = options.translate[key]
end
if options.readOnly then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; the table is read-only',
2
)
elseif options.noOverwrite and args[key] ~= nil then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; overwriting existing arguments is not permitted',
2
)
elseif val == nil then
--[[
-- If the argument is to be overwritten with nil, we need to erase
-- the value in metaArgs, so that __index, __pairs and __ipairs do
-- not use a previous existing value, if present; and we also need
-- to memoize the nil in nilArgs, so that the value isn't looked
-- up in the argument tables if it is accessed again.
--]]
metaArgs[key] = nil
nilArgs[key] = 'h'
else
metaArgs[key] = val
end
end
local function translatenext(invariant)
local k, v = next(invariant.t, invariant.k)
invariant.k = k
if k == nil then
return nil
elseif type(k) ~= 'string' or not options.backtranslate then
return k, v
else
local backtranslate = options.backtranslate[k]
if backtranslate == nil then
-- Skip this one. This is a tail call, so this won't cause stack overflow
return translatenext(invariant)
else
return backtranslate, v
end
end
end
metatable.__pairs = function ()
-- Called when pairs is run on the args table.
if not metatable.donePairs then
mergeArgs(argTables)
metatable.donePairs = true
end
return translatenext, { t = metaArgs }
end
local function inext(t, i)
-- This uses our __index metamethod
local v = t[i + 1]
if v ~= nil then
return i + 1, v
end
end
metatable.__ipairs = function (t)
-- Called when ipairs is run on the args table.
return inext, t, 0
end
return args
end
return arguments
ojpf6n6krtbq2o9ezlxv201kqkc2udp
Templat:Border
10
1016
22814
7376
2026-04-14T15:50:52Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Bingkai]] ke [[Templat:Border]] melalui lencongan
7375
wikitext
text/x-wiki
<includeonly>{{#invoke:Bingkai|border}}</includeonly><noinclude>{{pendokumenan}}</noinclude>
0vevfu4q0vbz5tgqzl8gf9geyq9ym5z
Modul:Category handler
828
1344
22791
10174
2026-04-14T13:23:15Z
Hakimi97
9
Dilindungi "[[Modul:Category handler]]": Laman berimpak tinggi ([Sunting=Benarkan penyelia sahaja] (tak terbatas) [Pindahkan=Benarkan penyelia sahaja] (tak terbatas))
6786
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- CATEGORY HANDLER --
-- --
-- This module implements the {{category handler}} template in Lua, --
-- with a few improvements: all namespaces and all namespace aliases --
-- are supported, and namespace names are detected automatically for --
-- the local wiki. This module requires [[Module:Namespace detect]] --
-- and [[Module:Yesno]] to be available on the local wiki. It can be --
-- configured for different wikis by altering the values in --
-- [[Module:Category handler/config]], and pages can be blacklisted --
-- from categorisation by using [[Module:Category handler/blacklist]]. --
-- --
--------------------------------------------------------------------------------
-- Load required modules
local yesno = require('Module:Yesno')
-- Lazily load things we don't always need
local mShared, mappings
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function trimWhitespace(s, removeBlanks)
if type(s) ~= 'string' then
return s
end
s = s:match('^%s*(.-)%s*$')
if removeBlanks then
if s ~= '' then
return s
else
return nil
end
else
return s
end
end
--------------------------------------------------------------------------------
-- CategoryHandler class
--------------------------------------------------------------------------------
local CategoryHandler = {}
CategoryHandler.__index = CategoryHandler
function CategoryHandler.new(data, args)
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
-- Set the title object
do
local pagename = obj:parameter('demopage')
local success, titleObj
if pagename then
success, titleObj = pcall(mw.title.new, pagename)
end
if success and titleObj then
obj.title = titleObj
if titleObj == mw.title.getCurrentTitle() then
obj._usesCurrentTitle = true
end
else
obj.title = mw.title.getCurrentTitle()
obj._usesCurrentTitle = true
end
end
-- Set suppression parameter values
for _, key in ipairs{'nocat', 'categories'} do
local value = obj:parameter(key)
value = trimWhitespace(value, true)
obj['_' .. key] = yesno(value)
end
do
local subpage = obj:parameter('subpage')
local category2 = obj:parameter('category2')
if type(subpage) == 'string' then
subpage = mw.ustring.lower(subpage)
end
if type(category2) == 'string' then
subpage = mw.ustring.lower(category2)
end
obj._subpage = trimWhitespace(subpage, true)
obj._category2 = trimWhitespace(category2) -- don't remove blank values
end
return obj
end
function CategoryHandler:parameter(key)
local parameterNames = self._data.parameters[key]
local pntype = type(parameterNames)
if pntype == 'string' or pntype == 'number' then
return self._args[parameterNames]
elseif pntype == 'table' then
for _, name in ipairs(parameterNames) do
local value = self._args[name]
if value ~= nil then
return value
end
end
return nil
else
error(string.format(
'invalid config key "%s"',
tostring(key)
), 2)
end
end
function CategoryHandler:isSuppressedByArguments()
return
-- See if a category suppression argument has been set.
self._nocat == true
or self._categories == false
or (
self._category2
and self._category2 ~= self._data.category2Yes
and self._category2 ~= self._data.category2Negative
)
-- Check whether we are on a subpage, and see if categories are
-- suppressed based on our subpage status.
or self._subpage == self._data.subpageNo and self.title.isSubpage
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
end
function CategoryHandler:shouldSkipBlacklistCheck()
-- Check whether the category suppression arguments indicate we
-- should skip the blacklist check.
return self._nocat == false
or self._categories == true
or self._category2 == self._data.category2Yes
end
function CategoryHandler:matchesBlacklist()
if self._usesCurrentTitle then
return self._data.currentTitleMatchesBlacklist
else
mShared = mShared or require('Module:Category handler/shared')
return mShared.matchesBlacklist(
self.title.prefixedText,
mw.loadData('Module:Category handler/blacklist')
)
end
end
function CategoryHandler:isSuppressed()
-- Find if categories are suppressed by either the arguments or by
-- matching the blacklist.
return self:isSuppressedByArguments()
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
end
function CategoryHandler:getNamespaceParameters()
if self._usesCurrentTitle then
return self._data.currentTitleNamespaceParameters
else
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
return mShared.getNamespaceParameters(
self.title,
mappings
)
end
end
function CategoryHandler:namespaceParametersExist()
-- Find whether any namespace parameters have been specified.
-- We use the order "all" --> namespace params --> "other" as this is what
-- the old template did.
if self:parameter('all') then
return true
end
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
for ns, params in pairs(mappings) do
for i, param in ipairs(params) do
if self._args[param] then
return true
end
end
end
if self:parameter('other') then
return true
end
return false
end
function CategoryHandler:getCategories()
local params = self:getNamespaceParameters()
local nsCategory
for i, param in ipairs(params) do
local value = self._args[param]
if value ~= nil then
nsCategory = value
break
end
end
if nsCategory ~= nil or self:namespaceParametersExist() then
-- Namespace parameters exist - advanced usage.
if nsCategory == nil then
nsCategory = self:parameter('other')
end
local ret = {self:parameter('all')}
local numParam = tonumber(nsCategory)
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
-- nsCategory is an integer
ret[#ret + 1] = self._args[numParam]
else
ret[#ret + 1] = nsCategory
end
if #ret < 1 then
return nil
else
return table.concat(ret)
end
elseif self._data.defaultNamespaces[self.title.namespace] then
-- Namespace parameters don't exist, simple usage.
return self._args[1]
end
return nil
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- Used for testing purposes.
return {
CategoryHandler = CategoryHandler
}
end
function p._main(args, data)
data = data or mw.loadData('Module:Category handler/data')
local handler = CategoryHandler.new(data, args)
if handler:isSuppressed() then
return nil
end
return handler:getCategories()
end
function p.main(frame, data)
data = data or mw.loadData('Module:Category handler/data')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = data.wrappers,
valueFunc = function (k, v)
v = trimWhitespace(v)
if type(k) == 'number' then
if v ~= '' then
return v
else
return nil
end
else
return v
end
end
})
return p._main(args, data)
end
return p
letwavu3yvlayfzew66uuwixmwebq5b
Modul:If empty
828
1553
22805
7221
2026-04-14T15:45:49Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Kalau kosong]] ke [[Modul:Module:If empty]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7221
Scribunto
text/plain
local p = {}
function p.main(frame)
local args = require('Modul:Arguments').getArgs(frame, {wrappers = 'Templat:Kalau kosong', removeBlanks = false})
local lastk = 0
for k,v in ipairs(args) do
if v ~= '' then
return v
end
lastk = k
end
end
return p
m9up657q88je92puwpoobbrvczx3t0z
22807
22805
2026-04-14T15:46:56Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Module:If empty]] ke [[Modul:If empty]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7221
Scribunto
text/plain
local p = {}
function p.main(frame)
local args = require('Modul:Arguments').getArgs(frame, {wrappers = 'Templat:Kalau kosong', removeBlanks = false})
local lastk = 0
for k,v in ipairs(args) do
if v ~= '' then
return v
end
lastk = k
end
end
return p
m9up657q88je92puwpoobbrvczx3t0z
22813
22807
2026-04-14T15:49:53Z
Hakimi97
9
22813
Scribunto
text/plain
local p = {}
function p.main(frame)
local args = require('Modul:Arguments').getArgs(frame, {wrappers = 'Templat:If empty', removeBlanks = false})
local lastk = 0
for k,v in ipairs(args) do
if v ~= '' then
return v
end
lastk = k
end
end
return p
1du48xao11yhyvrd6n83gajzfc3vo8c
Templat:If empty
10
1554
22810
7223
2026-04-14T15:48:26Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Kalau kosong]] ke [[Templat:If empty]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7223
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Kalau kosong|main}}<noinclude>{{pendokumenan}}</noinclude>
9ysr4ys0ftw4zexwxcccg51ur4nnymp
22812
22810
2026-04-14T15:48:48Z
Hakimi97
9
22812
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:If empty|main}}<noinclude>{{pendokumenan}}</noinclude>
mea1d3d3gr93aa5x6xmfqtnwgpradua
Modul:HTML attribute
828
1567
22799
7256
2026-04-14T15:43:34Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Atribut HTML]] ke [[Modul:HTML attribute]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7256
Scribunto
text/plain
require('strict')
local p = {}
local getArgs = require('Modul:Arguments').getArgs
function p._attribute(args)
local attribs = {}
for k, v in pairs(args) do
table.insert(attribs, k .. '="' .. v .. '"')
end
return table.concat(attribs, ' ')
end
function p.attribute(frame)
return p._attribute(getArgs(frame))
end
return p
4q2v4vth839d5myulrl2ql6ap3x773g
Templat:HTML attribute
10
1568
22797
7258
2026-04-14T15:42:17Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Atribut HTML]] ke [[Templat:HTML attribute]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7258
wikitext
text/x-wiki
{{#invoke:Atribut HTML|attribute}}<noinclude>{{pendokumenan}}</noinclude>
4mewzpvikiuasur2egqlmdv1zh45v5d
Modul:Border
828
1620
22801
7398
2026-04-14T15:44:24Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Bingkai]] ke [[Modul:Border]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
7398
Scribunto
text/plain
require('strict')
local p = {} --p stands for package
local getArgs = require('Modul:Arguments').getArgs
local make_style_string = require('Modul:Optional style').make_style_string
local CSS_unit = require('Modul:Unit CSS')._CSS_unit
function p.border_start(frame)
local args = getArgs(frame)
-- style args
local maxwidth = args['max-width'] or args.maxwidth or args[2] or 'none'
local display = args.display or 'block'
local bstyle = args.bstyle or args[3] or 'solid'
local bthickness = args.bthickness or args[4] or '1px'
local color = args.color or args[5] or '#000000'
local bgcolor = args.bgcolor or args[6] or '#FFFFFF'
local align = args.align or args[7] or 'left'
local position = args.position or args[8]
local padding = args.padding or args[9] or '5px'
local style = args.style or ''
local positionStyle
if position == 'left' then
positionStyle = ''
elseif position == 'right' then
positionStyle = 'position:relative;margin-left:auto;'
else
positionStyle = 'margin-left:auto;margin-right:auto;'
end
local styleArgs = {
['max-width'] = maxwidth,
['display'] = display,
['box-sizing'] = 'border-box',
['border'] = bstyle .. " " .. bthickness .. " " .. color,
['background-color'] = bgcolor,
['text-align'] = align,
['padding'] = padding,
['style'] = positionStyle .. " " .. style
}
local styleParam = make_style_string(styleArgs)
local divOpen = '<div class="wst-border" ' .. styleParam .. '>'
local trackingCat
if CSS_unit({maxwidth}) == 'px' then
trackingCat = '[[Kategori:Laman menggunakan lebar piksel (bingkai)]]'
else
trackingCat = ''
end
return divOpen .. trackingCat
end
local function border_end()
return '</div>'
end
function p.border(frame)
return p.border_start(frame) .. getArgs(frame)[1] .. border_end()
end
return p
dzcpfx91baai42jrhzf5soa5ggxf6mo
Templat:Border/kotak pasir
10
1627
22816
7393
2026-04-14T15:50:53Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Bingkai/kotak pasir]] ke [[Templat:Border/kotak pasir]]
7393
wikitext
text/x-wiki
<includeonly>{{#invoke:Bingkai/kotak_pasir|border}}</includeonly><noinclude>{{pendokumenan}}</noinclude>
p0zj4a5t2lfoj1s15uk5w9hago3b544
Indeks:Hikayat Pelanduk Jenaka Or. 1932.pdf
252
1717
22780
18719
2026-04-14T12:32:43Z
Hakimi97
9
22780
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=[[Hikayat Pelanduk Jenaka (Or. 1932)|حكاية فلندوق جناک]]
|Language=ms-arab
|Volume=
|Author=عبد الحكيم
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=بتاوي
|Year=1718
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=9
|Progress=C
|Transclusion=yes
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=Kelebaran imbasan
|Header=
|Footer=
|tmplver=
}}
efwn0eskqps9rbkd0y8cnx2dwyx9lpq
Pengguna:Hadithfajri/Laman utama
2
1848
22786
17979
2026-04-14T13:08:37Z
Hadithfajri
36
22786
wikitext
text/x-wiki
__NOTOC____NOEDITSECTION__
<templatestyles src="Laman_utama/styles.css" />
{{/Pengepala}}<!-------Kanan--------->
<div class="LU-kolom"><div class="LU-kolom-kiri">
{{Kotak berhias
|logo=Nuvola apps kpdf recolored.png
|tajuk=Jelajahi Wikisumber
|isi='''[[:Kategori:Kategori|Berdasarkan Kategori]]'''<br>
*[[:Kategori:Agama|Agama]] : [[:Kategori:Islam|Islam]], [[:Kategori:Kristian|Kristian]]
*[[:Kategori:Bahasa|Bahasa]] : [[:Kategori:Tatabahasa|Tatabahasa]], [[:Kategori:Kamus|Kamus]]
*[[:Kategori:Sastera|Sastera]] : [[:Kategori:Hikayat|Hikayat]], [[:Kategori:Syair|Syair]]
*[[:Kategori:Undang-undang Malaysia|Undang-undang Malaysia]]
'''[[:Kategori:Pengarang|Berdasarkan Pengarang]]'''}}
{{Kotak berhias|
|nombor=2
|logo=Foliate icon 2019.svg
|tajuk=Kerjasama Penyuntingan
|isi=Beberapa projek transkripsi yang sedang dijalankan:
===Projek transkripsi Wikisumber Cinta Bahasa Melayu===
* [[Index:The customs of the Malay kings especially concerning child birth.pdf|The customs of the Malay kings especially concerning child birth]] (1837)
* [[Index:Sesuatu yang disebutkan di dalam Quran darihal kitab Injil dan Taurat.pdf|Sesuatu yang disebutkan di dalam Quran darihal kitab Injil dan Taurat]] (1891)
* [[Index:Puji-pujian dan segala zabur Daud. The Psalter, or Psalms of David, with the Order for Morning and Evening Prayer daily throughout the year. Third edition.djvu|Puji-pujian dan segala zabur Daud. The Psalter, or Psalms of David, with the Order for Morning and Evening Prayer daily throughout the year. Third edition.]] (1836)
===Projek transkripsi (ruang nama Indeks dan Laman)===
* [[Index:Malaysia Act 1963.pdf|Akta Malaysia Tahun 1963]] (1963)
* [[Index:Agreement Relating to Malaysia between UK, N. Borneo, Sarawak and Singapore.djvu|Persetujuan berkenaan dengan penubuhan perlembagaan Malaysia]] (1963)
* [[Index:Ikhtisar Ceritera Daripada Raja-raja di Negeri Siam Or. 2011.pdf| Ikhtisar Ceritera Daripada Raja-raja di Negeri Siam Or. 2011]] (1823)
* [[Index:Manila Accord (31 July 1963).djvu|Manila Accord]] (1963)
* [[Index:Anchaman Komunis kapada Persekutuan Tanah Melayu.djvu|Anchaman Komunis kapada Persekutuan Tanah Melayu]] (1959)
* [[Index:Ukpga 19570060 en.djvu|Akta kemerdekaan Persekutuan Tanah Melayu]] (1957)
* [[Index:Hikayat Bayan Budiman.djvu|Hikayat Bayan Budiman]] (1371)
* [[Index:Hikayat Hang Tuah.djvu|Hikayat Hang Tuah]]
* [[Index:Malay-English vocabulary.djvu|Malay-English vocabulary]] (1912)
* [[Index:Vocabulary of the English and Malay languages.djvu|Vocabulary of the English and Malay languages]] (1837)
* [[Index:Bustan al-Katibin li as-Shibyan al-Mutaallimin.pdf|Bustan al-Katibin]] (1850)
* [[Index:Kitab Injil al-Kudus daripada Tuhan Isa al-Masih.pdf|Kitab Injil al-Kudus daripada Tuhan Isa al-Masih]] (1856)
* [[Index:Turjuman al-Mustafid.pdf|Turjuman al-Mustafid]] (1952)
* [[Index:Hikayat_Abdullah_(1880 version).pdf|Hikayat Abdullah]] (1880)
* [[Index:Pr_Terengganu.jpg|Batu Bersurat Terengganu]] (1303)
* [[Index:Sejarah_Melayu_Or._1703.pdf|Sulalatus Salatin]] (1834)
* [[Index:MSS Malay A2 Syair Perahu 1700.pdf|Syair Perahu (1700)]]}}
</div></div>
<!-------Kiri--------->
<div class="LU-kolom"><div class="LU-kolom-kanan">
{{Kotak berhias
|logo=Books_Flat_Icon_Vector.svg
|tajuk=Naskhah Yang Selesai Dibacaprufkan
|isi=<gallery heights=165 mode="packed">
Fail:The customs of the Malay kings especially concerning child birth.pdf|page=9|link=Adat Segala Raja-Raja Melayu|'''[[Pengarang:Abdullah_bin_Abdulkadir_Munsyi|Abdullah bin Abdulkadir Munsyi]]''',<br /> ''[[Adat Segala Raja-Raja Melayu]]'',<br /> 1837<br />
Fail:A practical Malay grammar (IA practicalmalaygr00sheliala).pdf|page=3|link=A Practical Malay Grammar|'''[[Pengarang:William Girdlestone Shellabear|W.G Shellabear]]''',<br /> ''[[A Practical Malay Grammar]]'',<br /> 1912<br />
Fail:Bustan al-Katibin li as-Shibyan al-Mutaallimin.pdf|page=7|link=Bustan al-Katibin|'''[[Pengarang:Raja Ali Haji|Raja Ali Haji]]''', <br /> ''[[Bustan al-Katibin|Bustan al-Katibin li as-Shibyan al-Mutaallimin]]'',<br />1850<br />
Fail:Collective volume with texts in Malay, Or. 3346.pdf|page=3|link=Syair Kampung Gelam Terbakar|'''[[Pengarang:Abdullah_bin_Abdulkadir_Munsyi|Abdullah bin Abdulkadir Munsyi]]''', <br /> ''[[Syair Kampung Gelam Terbakar]]'',<br />1847<br />
</gallery>}}
{{Kotak berhias
|nombor=2
|tajuk=Kenali Wikisumber
|isi=[[Image:Biblioteket, rummet Stockholm. Polonika. Polsk skrift - Skoklosters slott - 87713.tif|left|120px]]
'''Wikisumber''' ialah sebuah perpustakaan dalam talian yang mengandungi koleksi teks bebas dan dipelihara oleh sebuah komuniti yang aktif.
Anda boleh membantu kami mengembangkan perpustakaan ini. Kami menerima semua jenis teks '''[[w:Kandungan bebas|bebas]]''' (termasuk daripada [[w:Domain awam|domain awam]], yang diterbitkan dengan [[w:Lesen Dokumentasi Bebas GNU|Lesen Dokumentasi Bebas GNU]], dan yang diterbitkan dengan [[w:Creative Commons|Lesen Creative Commons Pengiktirafan-Perkongsian Serupa]]).
Untuk mengetahui bagaimana anda boleh menyumbang, sila kunjungi [[Wikisource:Bantuan|laman bantuan]]. Untuk menanyakan soalan, sila kunjungi laman [[Wikisource:Kedai Kopi|Kedai Kopi]].}}
</div></div>
<p style="clear: both;"></p>
{{kotak berhias
|nombor=3
|warna=merah
|kanan=3.5em
|tajuk=Wikisumber Dalam Bahasa Lain
|isi={{BahasaLain}}
}}
{{kotak berhias
|kanan=3.5em
|nombor=3
|warna=hijau
|logo=Wikimedia-logo.svg
|tajuk=Projek Wikimedia yang lain
|isi={{Projek saudara}}
}}
{{DISPLAYTITLE:<span style="position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);">{{FULLPAGENAME}}</span>}}
m07bi9rnza6jssvm79wfe1l2nfwkg3v
Indeks:Hikayat Iskandar Zulkarnain - volume 1 Or. 1696 1, Or. 1696 1.pdf
252
4001
22783
18716
2026-04-14T12:35:39Z
Hakimi97
9
22783
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=[[Hikayat Iskandar Zulkarnain|حکاية سلطان اسکندر ذوالکرنين]]
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=10
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
nd8wrqropvto5l7ncl1lv48eg1qgvyo
22784
22783
2026-04-14T12:35:53Z
Hakimi97
9
22784
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=[[Hikayat Iskandar Zulkarnain|حکاية سلطان اسکندر ذوالکرنين]]
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=10
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
l1gme64iwftnak24xemucehjs85dslm
Laman:Collective volume with texts in Malay, Or. 1722.pdf/55
250
4350
22794
14294
2026-04-14T13:55:13Z
Hadithfajri
36
22794
proofread-page
text/x-wiki
<noinclude><pagequality level="1" user="Hadithfajri" /></noinclude>{{rangkap|
ادا کفد سواة هاري \\ فرݢي برجالن راج بهري
دکاراڠ مسکين سواة فري \\ بوليه دبوة فنتون دان ڽاڽي
شعير دسکراڠ اورڠيڠ هينا \\ بوة ماين تيدق ݢون
باڽق چڠݢل تيدق کنا \\ جاڠن دباوا کسيني سنا
بوکنڽ سهيا فوڽ سوک \\ سبب دسوره سري فادک
مک شعير سهيا نن ريک \\ بوة ايبور هاتي يڠ دوک
اين سوره بيت کاراڠ \\ دفڽاڠة کوتا کاراڠ
سورڽ اودوه باڽق کوراڠ \\ تيدق ݢون فد اورڠ
تڠکو فتري سوره بيت \\ کاراڠ شعير سوره کات
بݢند هندق بوة چريت \\ کاران ادند فرݢي فيت
دري تيته توان فڠهول \\ سبب تکوة سرة مالو
دي مڽوره سده سلالو \\ تيدق بوله ننتي دهول
اف عقل بودي بيت \\ تيدق دافة لاݢ کات
تيک کالي سده فينت \\ سوره جوݢ بوة چريت}}
}}<noinclude></noinclude>
n9jnheaujqtnur4unhlbo6ow1k5k2gg
Indeks:Daftar Ejaan Melayu Za'ba AA0001098.pdf
252
5507
22821
17290
2026-04-15T03:28:13Z
Hakimi97
9
Percubaan
22821
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=Q134106972
|Title=
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=1
|Progress=C
|Transclusion=no
|Validation_date=April 2026
|Pages={{remove pages|pages=18,19,164,165|marked=yes}}
<pagelist
1="Tajuk"
2="–"
3="٣"
4="٤"
5="٥"
6="٦"
7="کندوڠن"
8="–"
9="٩"
10="١٠"
11="١١"
12="١٢"
13="١٣"
14="١٤"
15="١٥"
16="١٦"
17="١٧"
18to19="➔"
20="١٨"
21="١٩"
22="٢٠"
23="٢١"
24="٢٢"
25="٢٣"
26="٢٤"
27="٢٥"
28="٢٦"
29="٢٧"
30="٢٨"
31="٢٩"
32="٣٠"
33="٣١"
34="٣٢"
35="٣٣"
36="٣٤"
37="٣٥"
38="٣٦"
39="٣٧"
40="٣٨"
41="٣٩"
42="٤٠"
43="٤١"
44="٤٢"
45="٤٣"
46="٤٤"
47="٤٥"
48="٤٦"
49="٤٧"
50="٤٨"
51="٤٩"
52="٥٠"
53="٥١"
54="٥٢"
55="٥٣"
56="٥٤"
57="٥٥"
58="٥٦"
59="٥٧"
60="٥٨"
61=1
164to165="➔"
166=104
755=1
755to779=roman
776to779=–
/>
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
4xcm4cvatuwfkwb7bz9aelms8b2aewk
22822
22821
2026-04-15T03:28:50Z
Hakimi97
9
22822
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=Q134106972
|Title=
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=1
|Progress=C
|Transclusion=no
|Validation_date=
|Pages={{remove pages|pages=18,19,164,165|marked=yes}}
<pagelist
1="Tajuk"
2="–"
3="٣"
4="٤"
5="٥"
6="٦"
7="کندوڠن"
8="–"
9="٩"
10="١٠"
11="١١"
12="١٢"
13="١٣"
14="١٤"
15="١٥"
16="١٦"
17="١٧"
18to19="➔"
20="١٨"
21="١٩"
22="٢٠"
23="٢١"
24="٢٢"
25="٢٣"
26="٢٤"
27="٢٥"
28="٢٦"
29="٢٧"
30="٢٨"
31="٢٩"
32="٣٠"
33="٣١"
34="٣٢"
35="٣٣"
36="٣٤"
37="٣٥"
38="٣٦"
39="٣٧"
40="٣٨"
41="٣٩"
42="٤٠"
43="٤١"
44="٤٢"
45="٤٣"
46="٤٤"
47="٤٥"
48="٤٦"
49="٤٧"
50="٤٨"
51="٤٩"
52="٥٠"
53="٥١"
54="٥٢"
55="٥٣"
56="٥٤"
57="٥٥"
58="٥٦"
59="٥٧"
60="٥٨"
61=1
164to165="➔"
166=104
755=1
755to779=roman
776to779=–
/>
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
ohindvnxp4evoraihbhhvstmni2z21c
Indeks:Collection des principales chroniques malayes publiée par Éd. Dulaurier.pdf
252
5759
22785
22551
2026-04-14T12:37:33Z
Hakimi97
9
22785
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=collection
|wikidata_item=
|Title=[[Hikayat Pasai]] dan [[Sulalatus Salatin]]
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=10
|Progress=C
|Transclusion=no
|Validation_date=
|Pages=Muqaddimah - Hikayat Pasai
<pagelist from=10 to=133/>
Sulalatus Salatin
<pagelist from=134 to=402/>
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
odrr07unk625j79cq64k6k9z8rbhf51
Indeks:Hikayat Pelanduk Jinaka, and other texts in Malay and Bugis texts MSS Malay B 10.pdf
252
5784
22831
22605
2026-04-15T05:14:46Z
Hakimi97
9
22831
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=حكاية ڤلندوق جناک
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Hikayat_Pelanduk_Jinaka%2C_and_other_texts_in_Malay_and_Bugis_texts_MSS_Malay_B_10.pdf/page1-500px-Hikayat_Pelanduk_Jinaka%2C_and_other_texts_in_Malay_and_Bugis_texts_MSS_Malay_B_10.pdf.jpg
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
1116libbbkgtdfaeua8plr0dhymq0sb
22832
22831
2026-04-15T05:15:02Z
Hakimi97
9
22832
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=حكاية ڤلندوق جناک
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=1
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
tpq7nh9dmy2y2yxppd2s9f6vdagktf1
22833
22832
2026-04-15T05:15:56Z
Hakimi97
9
22833
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=حكاية ڤلندوق جناک
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=1
|Progress=OCR
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
eunkuje9pk3wqjqgytmfydlhurz89ta
Modul:Index template/data
828
5997
22788
22770
2026-04-14T13:21:10Z
Hakimi97
9
Utilize Modul:Arguments for getArgs
22788
Scribunto
text/plain
-- Modul:Index template/data
-- Fetches and merges Wikidata into template arguments for Malay Wikisource index pages.
local cfg = require('Modul:Index template/config')
local getArgs = require('Modul:Arguments').getArgs
local trim = mw.text.trim
-- Static mappings
-- Maps Wikidata instance-of (P31) entity IDs to index type strings.
local WIKIDATA_TYPE_MAP = {
['Q3331189'] = 'book',
['Q1238720'] = 'journal',
['Q28869365'] = 'journal',
['Q191067'] = 'journal',
['Q23622'] = 'dictionary',
['Q187685'] = 'phdthesis',
}
-- Maps index parameter names → Wikidata property IDs used for auto-population.
-- Comment out a line to disable auto-population for that field.
local INDEX_TO_WIKIDATA = {
subtitle = 'P1680',
language = 'P407',
volume = 'P478',
edition = 'P393',
author = 'P50',
translator = 'P655',
editor = 'P98',
illustrator = 'P110',
publisher = 'P123',
printer = 'P872',
address = 'P276',
publishedin = 'P291',
year = 'P577',
inception = 'P571',
parts = 'P747',
}
-- Argument normalisation
-- Build the translate map once at module load (inverts cfg.param_map).
-- cfg.param_map is { ['Title'] = 'title', ... }
-- translate must be { ['title'] = 'Title', ... } (lua-key → wikitext-key)
local TRANSLATE = {}
for titleCase, lowerCase in pairs(cfg.param_map) do
TRANSLATE[lowerCase] = titleCase
end
-- Wikidata helpers
-- Returns the datavalue.value of the first best statement for `propertyId`,
-- or nil if no statement with a datavalue exists.
local function getBestStatementValue(item, propertyId)
for _, statement in pairs(item:getBestStatements(propertyId)) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then return dv.value end
end
return nil
end
-- Main data builder
local function indexDataWithWikidata(frame)
local args = getArgs(frame, {
parentOnly = true, -- template args live in the parent frame
translate = TRANSLATE,
})
-- Resolve Wikidata item (if wikidata_item parameter was supplied).
local item = nil
if args.wikidata_item then
item = mw.wikibase.getEntity(args.wikidata_item)
if not item then
mw.addWarning(
'The Wikidata entity identifier [[d:' .. args.wikidata_item
.. '|' .. args.wikidata_item
.. ']] put in the "Wikidata entity" parameter of the Book page: '
.. 'does not seem valid.'
)
end
end
if not item then
return { args = args, item = nil }
end
-- Type: derived from instance-of (P31). Stop at the first recognised value.
if not args.type then
for _, statement in pairs(item:getBestStatements('P31')) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then
local mapped = WIKIDATA_TYPE_MAP[dv.value]
if mapped then
args.type = mapped
break
end
end
end
end
-- Cover image (P18).
if not args.image then
local imgValue = getBestStatementValue(item, 'P18')
if imgValue then args.image = imgValue end
end
-- Title: prefer P1476 (title), fall back to label, then sitelink display name.
if not args.title then
local value = item:formatStatements('P1476').value or ''
if value == '' then value = item:getLabel() or '' end
if value ~= '' then
local siteLink = item:getSitelink()
if siteLink then
value = '[[' .. siteLink .. '|' .. value .. ']]'
end
-- Append an edit-on-Wikidata icon.
args.title = value
.. ' [[File:OOjs UI icon edit-ltr.svg'
.. '|Lihat dan sunting data pada Wikidata'
.. '|10px|baseline|class=noviewer'
.. '|link=d:' .. item.id .. '#P1476]]'
end
end
-- Publication date (P577): extract the four-digit year from the timestamp.
if not args.year then
local timeValue = getBestStatementValue(item, 'P577')
if timeValue then
args.year = mw.ustring.sub(timeValue.time, 2, 5)
end
end
-- Remaining fields: bulk-populate from Wikidata when not already set.
for arg, propertyId in pairs(INDEX_TO_WIKIDATA) do
if not args[arg] then
local value = item:formatStatements(propertyId).value
if value and value ~= '' then
args[arg] = value
end
end
end
return { args = args, item = item }
end
-- Public API
local p = {}
function p.indexDataWithWikidata(frame)
return indexDataWithWikidata(frame)
end
return p
pnjd26dtha6xycuf1la3j74kftc747t
22818
22788
2026-04-15T03:23:58Z
Hakimi97
9
Code update
22818
Scribunto
text/plain
-- Modul:Index template/data
-- Fetches and merges Wikidata into template arguments for Malay Wikisource index pages.
local cfg = require('Modul:Index template/config')
local getArgs = require('Modul:Arguments').getArgs
-- Static mappings
-- Maps Wikidata instance-of (P31) entity IDs to index type strings.
local WIKIDATA_TYPE_MAP = {
['Q3331189'] = 'book',
['Q1238720'] = 'journal',
['Q28869365'] = 'journal',
['Q191067'] = 'journal',
['Q23622'] = 'dictionary',
['Q187685'] = 'phdthesis',
}
-- Maps index parameter names → Wikidata property IDs used for auto-population.
-- Comment out a line to disable auto-population for that field.
local INDEX_TO_WIKIDATA = {
subtitle = 'P1680',
language = 'P407',
volume = 'P478',
edition = 'P393',
author = 'P50',
translator = 'P655',
editor = 'P98',
illustrator = 'P110',
publisher = 'P123',
printer = 'P872',
address = 'P276',
publishedin = 'P291',
year = 'P577',
inception = 'P571',
parts = 'P747',
}
-- Argument normalisation
-- Build the translate map once at module load (inverts cfg.param_map).
-- cfg.param_map is { ['Title'] = 'title', ... } (wikitext-key → lua-key)
-- TRANSLATE must be { ['title'] = 'Title', ... } (lua-key → wikitext-key)
-- Modul:Arguments uses this to look up Title-Case wikitext params by lua key.
local TRANSLATE = {}
for titleCase, lowerCase in pairs(cfg.param_map) do
TRANSLATE[lowerCase] = titleCase
end
-- Wikidata helpers
-- Returns the datavalue.value of the first best statement for `propertyId`,
-- or nil if no statement with a datavalue exists.
local function getBestStatementValue(item, propertyId)
for _, statement in pairs(item:getBestStatements(propertyId)) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then return dv.value end
end
return nil
end
-- Main data builder
local function indexDataWithWikidata(frame)
local args = getArgs(frame, {
parentOnly = true, -- template args live in the parent frame
translate = TRANSLATE,
})
-- Resolve Wikidata item (if wikidata_item parameter was supplied).
local item = nil
if args.wikidata_item then
item = mw.wikibase.getEntity(args.wikidata_item)
if not item then
mw.addWarning(
'The Wikidata entity identifier [[d:' .. args.wikidata_item
.. '|' .. args.wikidata_item
.. ']] put in the "Wikidata entity" parameter of the Book page: '
.. 'does not seem valid.'
)
end
end
if not item then
return { args = args, item = nil }
end
-- Type: derived from instance-of (P31). Stop at the first recognised value.
if not args.type then
for _, statement in pairs(item:getBestStatements('P31')) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then
local mapped = WIKIDATA_TYPE_MAP[dv.value]
if mapped then
args.type = mapped
break
end
end
end
end
-- Cover image (P18).
if not args.image then
local imgValue = getBestStatementValue(item, 'P18')
if imgValue then args.image = imgValue end
end
-- Title: prefer P1476 (title), fall back to label, then sitelink display name.
if not args.title then
local value = item:formatStatements('P1476').value or ''
if value == '' then value = item:getLabel() or '' end
if value ~= '' then
local siteLink = item:getSitelink()
if siteLink then
value = '[[' .. siteLink .. '|' .. value .. ']]'
end
-- Append an edit-on-Wikidata icon.
args.title = value
.. ' [[File:OOjs UI icon edit-ltr.svg'
.. '|Lihat dan sunting data pada Wikidata'
.. '|10px|baseline|class=noviewer'
.. '|link=d:' .. item.id .. '#P1476]]'
end
end
-- Publication date (P577): extract the four-digit year from the timestamp.
if not args.year then
local timeValue = getBestStatementValue(item, 'P577')
if timeValue then
args.year = mw.ustring.sub(timeValue.time, 2, 5)
end
end
-- Remaining fields: bulk-populate from Wikidata when not already set.
for arg, propertyId in pairs(INDEX_TO_WIKIDATA) do
if not args[arg] then
local value = item:formatStatements(propertyId).value
if value and value ~= '' then
args[arg] = value
end
end
end
return { args = args, item = item }
end
-- Public API
local p = {}
function p.indexDataWithWikidata(frame)
return indexDataWithWikidata(frame)
end
return p
cgjdp1tx0igw94l6bdbes1a2s1up5hx
22829
22818
2026-04-15T05:08:55Z
Hakimi97
9
Code consolidation
22829
Scribunto
text/plain
-- Modul:Index template/data
-- Fetches and merges Wikidata into template arguments for Malay Wikisource index pages.
local cfg = require('Modul:Index template/config')
local getArgs = require('Modul:Arguments').getArgs
-- Static mappings
-- Maps Wikidata instance-of (P31) entity IDs to index type strings.
local WIKIDATA_TYPE_MAP = {
['Q3331189'] = 'book',
['Q1238720'] = 'journal',
['Q28869365'] = 'journal',
['Q191067'] = 'journal',
['Q23622'] = 'dictionary',
['Q187685'] = 'phdthesis',
}
-- Maps index parameter names → Wikidata property IDs used for auto-population.
-- Comment out a line to disable auto-population for that field.
local INDEX_TO_WIKIDATA = {
subtitle = 'P1680',
language = 'P407',
volume = 'P478',
edition = 'P393',
author = 'P50',
translator = 'P655',
editor = 'P98',
illustrator = 'P110',
publisher = 'P123',
printer = 'P872',
address = 'P276',
publishedin = 'P291',
year = 'P577',
inception = 'P571',
parts = 'P747',
}
-- Wikidata helpers
-- Returns the datavalue.value of the first best statement for `propertyId`,
-- or nil if no statement with a datavalue exists.
local function getBestStatementValue(item, propertyId)
for _, statement in pairs(item:getBestStatements(propertyId)) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then return dv.value end
end
return nil
end
-- Main data builder
local function indexDataWithWikidata(frame)
local args = getArgs(frame, {
parentOnly = true, -- template args live in the parent frame
translate = cfg.translate,
})
-- Resolve Wikidata item (if wikidata_item parameter was supplied).
local item = nil
if args.wikidata_item then
item = mw.wikibase.getEntity(args.wikidata_item)
if not item then
mw.addWarning(
'The Wikidata entity identifier [[d:' .. args.wikidata_item
.. '|' .. args.wikidata_item
.. ']] put in the "Wikidata entity" parameter of the Book page: '
.. 'does not seem valid.'
)
end
end
if not item then
return { args = args, item = nil }
end
-- Type: derived from instance-of (P31). Stop at the first recognised value.
if not args.type then
for _, statement in pairs(item:getBestStatements('P31')) do
local dv = statement.mainsnak.datavalue
if dv ~= nil then
local mapped = WIKIDATA_TYPE_MAP[dv.value]
if mapped then
args.type = mapped
break
end
end
end
end
-- Cover image (P18).
if not args.image then
local imgValue = getBestStatementValue(item, 'P18')
if imgValue then args.image = imgValue end
end
-- Title: prefer P1476 (title), fall back to label, then sitelink display name.
if not args.title then
local value = item:formatStatements('P1476').value or ''
if value == '' then value = item:getLabel() or '' end
if value ~= '' then
local siteLink = item:getSitelink()
if siteLink then
value = '[[' .. siteLink .. '|' .. value .. ']]'
end
-- Append an edit-on-Wikidata icon.
args.title = value
.. ' [[File:OOjs UI icon edit-ltr.svg'
.. '|Lihat dan sunting data pada Wikidata'
.. '|10px|baseline|class=noviewer'
.. '|link=d:' .. item.id .. '#P1476]]'
end
end
-- Publication date (P577): extract the four-digit year from the timestamp.
if not args.year then
local timeValue = getBestStatementValue(item, 'P577')
if timeValue then
args.year = mw.ustring.sub(timeValue.time, 2, 5)
end
end
-- Remaining fields: bulk-populate from Wikidata when not already set.
for arg, propertyId in pairs(INDEX_TO_WIKIDATA) do
if not args[arg] then
local value = item:formatStatements(propertyId).value
if value and value ~= '' then
args[arg] = value
end
end
end
return { args = args, item = item }
end
-- Public API
local p = {}
function p.indexDataWithWikidata(frame)
return indexDataWithWikidata(frame)
end
return p
so5lpvj1avocz6koq97xw4pkepm68wk
Modul:Index template
828
5998
22789
22775
2026-04-14T13:21:26Z
Hakimi97
9
Utilize Modul:Arguments for getArgs
22789
Scribunto
text/plain
--[=[
Latest update: 14th April 2026
This is a module to implement logic for [[MediaWiki:Proofreadpage index template]],
to render the book/index metadata panel for Malay Wikisource index pages.
]=]
local ISO_639 = require('Modul:ISO 639')
local messageBox = require('Module:Message box')
local category_handler = require('Module:Category handler')._main
local cfg = require('Modul:Index template/config')
local getArgs = require('Modul:Arguments').getArgs
-- Low-level markup helpers
local function construct_cat(cat)
return '[[Kategori:' .. cat .. ']]'
end
local function construct_cat_link(cat, text)
return '[[:Kategori:' .. cat .. '|' .. (text or cat) .. ']]'
end
-- Builds a single labelled metadata row.
local function construct_field(id, content)
if id == nil or content == nil then return nil end
if not cfg.headings[id] then error(cfg.missing_heading_id(id)) end
return mw.html.create('tr')
:attr('id', 'ws-index-' .. id .. '-row')
:addClass('ws-index-row')
:tag('th')
:attr('scope', 'row')
:attr('id', 'ws-index-' .. id .. '-label')
:addClass('ws-index-label')
:wikitext(cfg.headings[id].txt)
:done()
:tag('td')
:attr('id', 'ws-index-' .. id .. '-value')
:addClass('ws-index-value')
:wikitext(content)
:allDone()
end
-- Conditionally adds a metadata row and the appropriate tracking category.
-- If `content` is truthy the row is added plus `with_cat` (if given).
-- Otherwise only `without_cat` is emitted (if given).
local function add_field(tbl, html, id, content, with_cat, without_cat)
if content then
tbl:node(construct_field(id, content))
if with_cat then html:wikitext(construct_cat(with_cat)) end
elseif without_cat then
html:wikitext(construct_cat(without_cat))
end
end
-- Wikidata link helpers
local function addWikidataToLink(page, label, category)
local title = mw.title.new(page)
if title == nil then
return '[[' .. page .. '|' .. label .. ']]'
end
if title.isRedirect then title = title.redirectTarget end
local tag = mw.html.create('span')
local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
tag:wikitext('[[' .. page .. '|' .. label .. ']]')
if itemId then
tag:wikitext(
' [[Image:Wikidata.svg|10px|link=d:' .. itemId .. '|Lihat maklumat di Wikidata]]'
)
if category then tag:wikitext('[[Kategori:' .. category .. ']]') end
end
return tostring(tag)
end
-- Walks wikilinks inside `wikitext` and augments each with a Wikidata icon
-- when the linked page has a Wikidata entity.
local function withWikidataLink(wikitext, category)
if wikitext == nil then return nil end
-- Try bare [[Page]] links first …
local result = mw.ustring.gsub(wikitext, '%[%[([^|%]]*)%]%]', function(page)
return addWikidataToLink(page, mw.ustring.gsub(page, '%.*/', ''), category)
end)
if result ~= wikitext then return result end
-- … then [[Page|Label]] links.
return mw.ustring.gsub(wikitext, '%[%[([^|]*)|([^|%]]*)%]%]', function(page, link)
return addWikidataToLink(page, link, category)
end)
end
-- Formats a contributor field (author / translator / editor).
-- With a Wikidata item: augments links with Wikidata icons.
-- Without: wraps bare (non-wikilinked) names in {{Al|}}.
local function format_person(value, item)
if item then return withWikidataLink(value) end
if value:find('%[%[') then return value end
return '{{Al|' .. value .. '}}'
end
-- Progress / transclusion status rows
local function construct_status_field(args, statusArgs)
local key = statusArgs.key
local config_key = statusArgs.config_key or key
local index_status = args[key] or '_missing'
local sd = cfg[config_key][index_status] or cfg[config_key]['_default']
local txt = sd.txt
if type(txt) == 'function' then txt = txt(index_status) end
local display = sd.error
and ('<span class="error">' .. txt .. '</span>')
or construct_cat_link(sd.cat, txt)
return {
row = construct_field(key, display),
cat = construct_cat(sd.cat),
}
end
-- Indicator builder
local function construct_indicator(frame, iData)
local parts = { iData.image, iData.width or '20px' }
if iData.alt then table.insert(parts, 'alt=' .. iData.alt) end
if iData.link then table.insert(parts, 'link=' .. iData.link) end
if iData.caption then table.insert(parts, iData.caption) end
return frame:extensionTag{
name = 'indicator',
content = '[[' .. table.concat(parts, '|') .. ']]',
args = { name = iData.name },
}
end
-- Talk-page remarks
local p = {}
function p._index_talk_remarks(args)
if not args.talkPageTitle then
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
end
local text = cfg.talkremarks.text(args)
local cat = category_handler({ construct_cat(cfg.talkremarks.cat) }) or ''
local notes = ''
if args.notes then
notes = mw.html.create('div')
:addClass('ombox-content')
:css({
['text-align'] = 'left',
['max-height'] = '5.5em',
['overflow'] = 'scroll',
['padding'] = '0.25em',
['margin'] = '0.25em',
['border-style'] = 'dashed',
})
:newline()
:wikitext(args.notes .. cat)
:newline()
:allDone()
end
return messageBox.main('ombox', {
type = 'content',
image = '[[File:Ambox important.svg|24px]]',
style = 'box-sizing:border-box;margin:-0.93em auto 0.0em;text-align:center;width:100%;',
textstyle = 'font-size:93%;text-decoration:none;',
text = text .. tostring(notes),
})
end
function p.index_talk_remarks(frame)
local args = getArgs(frame) -- trim + blank-removal handled automatically
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
return p._index_talk_remarks(args)
end
-- Language resolution
-- Resolves the display language string and emits language-related tracking
-- categories onto `html`. Returns the display string, or nil if unavailable.
local function resolve_language(args, item, html)
local displayLang = nil
local languageCount = 0
if item then
local languages = item:formatPropertyValues(
'P407', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value
if languages and mw.text.trim(languages) ~= '' then
displayLang = languages
for language in languages:gmatch('([^,]+)') do
language = mw.text.trim(language)
if language ~= '' then
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam ' .. language
))
end
end
end
end
if not displayLang and args.language then
local displayLangs = {}
for _, l in ipairs(mw.text.split(args.language, ',%s*', false)) do
local lang = mw.text.trim(l)
if lang ~= '' then
local langName = ISO_639.language_name(lang, lang)
table.insert(displayLangs, langName)
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam bahasa ' .. langName
))
end
end
if #displayLangs > 0 then
displayLang = table.concat(displayLangs, ', ')
end
end
if displayLang then
html:wikitext(construct_cat('Karya dengan maklumat bahasa'))
if languageCount > 1 then
html:wikitext(construct_cat('Laman indeks karya yang asal dalam pelbagai bahasa'))
end
else
html:wikitext(construct_cat('Laman indeks karya tanpa maklumat bahasa'))
end
return displayLang
end
-- Metadata table
-- File formats that should render as a link to the index file page.
local LINKABLE_SOURCES = {
djvu=true, pdf=true, png=true, gif=true,
tif=true, ogg=true, ogv=true, webm=true,
}
local function build_metadata(args, item, html)
local t = mw.html.create('table'):attr('id', 'ws-index-metadata')
-- Title
if args.title then
local titleContent
if item then
titleContent = withWikidataLink(args.title)
elseif args.title:find('%[%[') then
titleContent = args.title
else
titleContent = '[[' .. args.title .. ']]'
end
t:node(construct_field('title', titleContent))
else
mw.addWarning('Anda perlu isi medan tajuk borang.')
end
-- Subtitle
add_field(t, html, 'subtitle', withWikidataLink(args.subtitle))
-- Language (complex; categories emitted inside resolve_language)
add_field(t, html, 'language', resolve_language(args, item, html))
-- Simple bibliographic fields
add_field(t, html, 'volume',
args.volume,
'Karya dengan maklumat nombor jilid',
'Karya tanpa maklumat nombor jilid')
add_field(t, html, 'edition',
args.edition,
'Karya dengan maklumat edisi',
'Karya tanpa maklumat edisi')
-- Author (also emits per-author categories from Wikidata)
if args.author then
t:node(construct_field('author', format_person(args.author, item)))
html:wikitext(construct_cat('Karya dengan maklumat pengarang'))
if item then
local authors = item:formatPropertyValues(
'P50', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value or ''
for author in authors:gmatch('([^,]+)') do
html:wikitext(construct_cat('Karya ' .. mw.text.trim(author)))
end
end
else
html:wikitext(construct_cat('Karya tanpa maklumat pengarang'))
end
-- Contributor fields
add_field(t, html, 'translator',
args.translator and format_person(args.translator, item),
'Karya dengan maklumat penterjemah',
'Karya tanpa maklumat penterjemah')
add_field(t, html, 'editor',
args.editor and format_person(args.editor, item),
'Karya dengan maklumat penyunting',
'Karya tanpa maklumat penyunting')
add_field(t, html, 'illustrator',
args.illustrator and withWikidataLink(args.illustrator),
'Karya dengan maklumat pengilustrasi',
'Karya tanpa maklumat pengilustrasi')
add_field(t, html, 'publisher',
args.publisher and withWikidataLink(args.publisher),
'Karya dengan maklumat penerbit',
'Karya tanpa maklumat penerbit')
-- Address / Published-in (mutually exclusive)
if args.address then
t:node(construct_field('address', withWikidataLink(args.address)))
html:wikitext(construct_cat('Karya dengan maklumat alamat'))
elseif args.publishedin then
t:node(construct_field('publishedin', withWikidataLink(args.publishedin)))
html:wikitext(construct_cat('Karya dengan maklumat alamat penerbitan'))
else
html:wikitext(construct_cat('Karya tanpa maklumat alamat penerbitan'))
end
-- Year / Inception (mutually exclusive)
if args.year then
t:node(construct_field('year', withWikidataLink(args.year)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh'))
html:wikitext(construct_cat('Karya tahun ' .. args.year))
elseif args.inception then
t:node(construct_field('inception', withWikidataLink(args.inception)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh terawal'))
else
html:wikitext(construct_cat('Karya tanpa maklumat tarikh'))
end
add_field(t, html, 'printer',
args.printer and withWikidataLink(args.printer),
'Karya dengan maklumat pencetak',
'Karya tanpa maklumat pencetak')
-- Source (linkable formats get a file-page link)
local src = args.source
t:node(construct_field('source',
src and LINKABLE_SOURCES[src]
and '[[:Fail:' .. mw.title.getCurrentTitle().text .. '|' .. src .. ']]'
or src
))
-- Progress & transclusion status
local progress_data = construct_status_field(args, { key = 'progress', config_key = 'status' })
local transclusion_data = construct_status_field(args, { key = 'transclusion' })
t:node(progress_data.row); html:wikitext(progress_data.cat)
t:node(transclusion_data.row); html:wikitext(transclusion_data.cat)
-- Validation date
local vdate = args.validation_date
if vdate then
local vcat = cfg.validation_cats.dated(vdate)
t:node(construct_field('validation_date', construct_cat_link(vcat, vdate)))
html:wikitext(construct_cat(vcat))
elseif args.progress == 'T' then
html:wikitext(construct_cat(cfg.validation_cats.undated))
end
-- Standard identifiers
for _, id in ipairs({ 'isbn', 'oclc', 'lccn', 'ark', 'doi' }) do
local val = args[id]
if val then
local link_fn = cfg.url_gens[id]
t:node(construct_field(id, link_fn and link_fn(val, val) or val))
end
end
add_field(t, html, 'volumes', args.volumes)
return t
end
-- Cover image
--[=[
Decision tree (evaluated in order):
1. Full [[...]] wikilink spec supplied → use as-is
2. Bare filename (has extension) → strip namespace prefix, rewrap
3. Audiovisual timestamp string → treat as thumbtime= value (→ case 5)
4. Multipage (DjVu/PDF) + file exists → page= thumbnail
5. Audiovisual + file exists → thumbtime= thumbnail
6. Any other type + file exists → plain file link
7. File does not exist → placeholder + missing category
--]=]
local function build_cover(args)
local image_number = tonumber(args.image)
-- Treat a bare timestamp string (e.g. "83" or "1:23") as a thumbtime value.
if args.image and not image_number
and args.source_type == 'audiovisual'
and mw.ustring.match(args.image, '^%d+[%d:]*$') then
image_number = args.image
end
local image_spec
local cats = {}
if not image_number and args.image and mw.ustring.find(args.image, '^%[%[') then
-- Case 1: full wikilink spec
image_spec = args.image
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif not image_number and args.image and mw.ustring.find(args.image, '%.%w+$') then
-- Case 2: bare filename — strip any recognised File namespace prefix
local image_name = args.image
local file_ns = mw.site.namespaces[6]
local prefixes = { file_ns.name, file_ns.canonicalName }
for _, alias in ipairs(file_ns.aliases) do
table.insert(prefixes, alias)
end
for _, prefix in ipairs(prefixes) do
image_name = mw.ustring.gsub(image_name, '^' .. prefix .. ':', '')
image_name = mw.ustring.gsub(image_name, '^' .. prefix:lower() .. ':', '')
end
image_spec = '[[' .. mw.title.makeTitle('Fail', image_name).prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif args.source_type == 'multipage' and args.file_exists then
-- Case 4: DjVu / PDF page thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|page=' .. (image_number or 1)
.. '|class=ws-cover]]'
elseif args.source_type == 'audiovisual' and args.file_exists then
-- Case 5: audio / video timestamp thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|thumbtime=' .. (image_number or 0)
.. '|class=ws-cover]]'
elseif args.file_exists then
-- Case 6: image or unknown type
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
else
-- Case 7: file missing — fall back to placeholder
local image_link = args.fileTitle.prefixedText
if not mw.ustring.find(args.fileTitle.rootText, '^.*%.%w+') then
image_link = 'Special:Upload'
end
image_spec = '[[' .. cfg.cover.image
.. '|' .. cfg.cover.width
.. '|link=' .. image_link
.. '|class=ws-cover]]'
table.insert(cats, construct_cat(cfg.cover_cats.missing))
end
return image_spec .. table.concat(cats)
end
-- Argument setup
-- Resolves all derived values and performs every expensive DB lookup exactly
-- once. Anything that touches the DB (file.exists, title.exists) lives here
-- and nowhere else, making the cost immediately visible to maintainers.
local function process_args(args)
local pageTitle = mw.title.getCurrentTitle()
args.talkPageTitle = pageTitle.talkPageTitle
args.fileTitle = mw.title.makeTitle('Fail', pageTitle.rootText)
args.source_type = cfg.cover_cats.file_types[args.source]
args.file_exists = args.fileTitle.file.exists -- expensive: DB lookup
args.talk_exists = args.talkPageTitle.exists -- expensive: DB lookup
return args
end
-- Main entry point
local INDICATOR_ORDER = { 'pagegame', 'purge', 'book2scroll', 'bookreader' }
local function indexTemplate(frame)
local styles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modul:Index template/styles.css' },
}
local data = (require 'Modul:Index_template/data').indexDataWithWikidata(frame)
local args, item = data.args, data.item
args = process_args(args)
-- Scan the talk page for formatting notes unless notes were supplied directly.
local talkremarks = ''
local talk_page_exists = args.talk_exists
if talk_page_exists and not args.notes then
local content = args.talkPageTitle.content
for _, keyword in ipairs(cfg.talkremarks.keywords) do
local pattern = keyword.alone
and '==( *' .. keyword.pattern .. ' *)=='
or '==([^=%n]*' .. keyword.pattern .. '[^=%n]*)=='
local section = mw.ustring.match(content, pattern)
if section then
args.notes = mw.getCurrentFrame():callParserFunction(
'#lsth',
args.talkPageTitle.prefixedText,
mw.text.trim(section)
)
break
end
end
end
if talk_page_exists then
talkremarks = p._index_talk_remarks(args)
end
local html = mw.html.create()
-- Wikidata indicator
if item then
html:wikitext('[[Kategori:Karya dengan ID Wikidata]]')
html:wikitext(
'<indicator name="wikidata">[[File:Wikidata.svg|20px|ID Wikidata|link=d:'
.. item.id .. ']]</indicator>'
)
else
html:wikitext('[[Kategori:Karya tanpa ID Wikidata]]')
end
-- Tool indicators
local indicators_cfg = require('Modul:Index template/indicators')
for _, key in ipairs(INDICATOR_ORDER) do
html:wikitext(construct_indicator(frame, indicators_cfg[key]))
end
local metadataTable = build_metadata(args, item, html)
local coverImage = build_cover(args)
-- Outer layout: [cover + metadata + pagelist] | [remarks]
local outerRow = html:tag('table')
:attr('id', 'ws-index-container')
:tag('tr')
outerRow:tag('td')
:attr('id', 'ws-index-main-cell')
:tag('table')
:attr('id', 'ws-index-main-table')
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-cover-container')
:wikitext(coverImage)
:done()
:node(metadataTable)
:done()
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-pagelist-container')
:addClass('mw-collapsible')
:tag('em'):wikitext(cfg.pagelist.pages.txt):done()
:wikitext(' ')
:tag('span')
:attr('id', 'ws-index-pagelist-legend')
:wikitext(cfg.pagelist.legend.txt)
:done()
:tag('div')
:attr('id', 'ws-index-pagelist')
:addClass('index-pagelist mw-collapsible-content')
:newline()
:wikitext(args.pages and mw.text.trim(args.pages))
:newline()
if args.remarks then
outerRow:tag('td')
:attr('id', 'ws-index-remarks')
:newline()
:wikitext(frame:preprocess(args.remarks))
else
outerRow:tag('td'):attr('id', 'ws-index-remarks-empty')
end
-- Notes block
if args.notes then
html:tag('div'):attr('id', 'ws-index-notes'):wikitext(args.notes)
end
-- Tracking categories
if cfg.type_cats[args.type] then
html:wikitext(construct_cat(cfg.type_cats[args.type]))
end
if cfg.source_cats[args.source] then
html:wikitext(construct_cat(cfg.source_cats[args.source]))
elseif args.source ~= 'lain-lain' then
html:wikitext(construct_cat('Indeks fail format lain'))
end
html:wikitext(construct_cat('Indeks'))
if not args.remarks then
html:wikitext(construct_cat('Laman berindeks'))
end
return talkremarks .. styles .. tostring(html)
end
function p.indexTemplate(frame)
return indexTemplate(frame)
end
return p
toa7dam8dih3f77h8rlosuoxbvm5a5g
22820
22789
2026-04-15T03:24:28Z
Hakimi97
9
Code update
22820
Scribunto
text/plain
--[=[
Latest update: 15th April 2026
This is a module to implement logic for [[MediaWiki:Proofreadpage index template]],
to render the book/index metadata panel for Malay Wikisource index pages.
]=]
local ISO_639 = require('Modul:ISO 639')
local messageBox = require('Module:Message box')
local category_handler = require('Module:Category handler')._main
local cfg = require('Modul:Index template/config')
-- Low-level markup helpers
local function construct_cat(cat)
return '[[Kategori:' .. cat .. ']]'
end
local function construct_cat_link(cat, text)
return '[[:Kategori:' .. cat .. '|' .. (text or cat) .. ']]'
end
-- Builds a single labelled metadata row.
local function construct_field(id, content)
if id == nil or content == nil then return nil end
if not cfg.headings[id] then error(cfg.missing_heading_id(id)) end
return mw.html.create('tr')
:attr('id', 'ws-index-' .. id .. '-row')
:addClass('ws-index-row')
:tag('th')
:attr('scope', 'row')
:attr('id', 'ws-index-' .. id .. '-label')
:addClass('ws-index-label')
:wikitext(cfg.headings[id].txt)
:done()
:tag('td')
:attr('id', 'ws-index-' .. id .. '-value')
:addClass('ws-index-value')
:wikitext(content)
:allDone()
end
-- Conditionally adds a metadata row and the appropriate tracking category.
-- If `content` is truthy the row is added plus `with_cat` (if given).
-- Otherwise only `without_cat` is emitted (if given).
local function add_field(tbl, html, id, content, with_cat, without_cat)
if content then
tbl:node(construct_field(id, content))
if with_cat then html:wikitext(construct_cat(with_cat)) end
elseif without_cat then
html:wikitext(construct_cat(without_cat))
end
end
-- Wikidata link helpers
local function addWikidataToLink(page, label, category)
local title = mw.title.new(page)
if title == nil then
return '[[' .. page .. '|' .. label .. ']]'
end
if title.isRedirect then title = title.redirectTarget end
local tag = mw.html.create('span')
local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
tag:wikitext('[[' .. page .. '|' .. label .. ']]')
if itemId then
tag:wikitext(
' [[Image:Wikidata.svg|10px|link=d:' .. itemId .. '|Lihat maklumat di Wikidata]]'
)
if category then tag:wikitext('[[Kategori:' .. category .. ']]') end
end
return tostring(tag)
end
-- Walks wikilinks inside `wikitext` and augments each with a Wikidata icon
-- when the linked page has a Wikidata entity.
local function withWikidataLink(wikitext, category)
if wikitext == nil then return nil end
-- Try bare [[Page]] links first …
local result = mw.ustring.gsub(wikitext, '%[%[([^|%]]*)%]%]', function(page)
return addWikidataToLink(page, mw.ustring.gsub(page, '%.*/', ''), category)
end)
if result ~= wikitext then return result end
-- … then [[Page|Label]] links.
return mw.ustring.gsub(wikitext, '%[%[([^|]*)|([^|%]]*)%]%]', function(page, link)
return addWikidataToLink(page, link, category)
end)
end
-- Formats a contributor field (author / translator / editor).
-- With a Wikidata item: augments links with Wikidata icons.
-- Without: wraps bare (non-wikilinked) names in {{Al|}}.
local function format_person(value, item)
if item then return withWikidataLink(value) end
if value:find('%[%[') then return value end
return '{{Al|' .. value .. '}}'
end
-- Progress / transclusion status rows
local function construct_status_field(args, statusArgs)
local key = statusArgs.key
local config_key = statusArgs.config_key or key
local index_status = args[key] or '_missing'
local sd = cfg[config_key][index_status] or cfg[config_key]['_default']
local txt = sd.txt
if type(txt) == 'function' then txt = txt(index_status) end
local display = sd.error
and ('<span class="error">' .. txt .. '</span>')
or construct_cat_link(sd.cat, txt)
return {
row = construct_field(key, display),
cat = construct_cat(sd.cat),
}
end
-- Indicator builder
-- Builds one <indicator> tag from an indicator config entry.
-- `link` and `caption` may be plain strings or functions called with `args`.
-- An optional `include` predicate (also called with `args`) gates rendering;
-- defaults to always-show when absent.
local function construct_indicator(args, iData)
local include = iData.include or function() return true end
if not include(args) then return '' end
local parts = { iData.image, iData.width or '20px' }
if iData.alt then table.insert(parts, 'alt=' .. iData.alt) end
local link = iData.link
if type(link) == 'function' then link = link(args) end
if link then table.insert(parts, 'link=' .. link) end
local caption = iData.caption
if type(caption) == 'function' then caption = caption(args) end
if caption then table.insert(parts, caption) end
return mw.getCurrentFrame():extensionTag{
name = 'indicator',
content = '[[' .. table.concat(parts, '|') .. ']]',
args = { name = iData.name },
}
end
-- Talk-page remarks
local p = {}
function p._index_talk_remarks(args)
if not args.talkPageTitle then
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
end
local text = cfg.talkremarks.text(args)
local cat = category_handler({ construct_cat(cfg.talkremarks.cat) }) or ''
local notes = ''
if args.notes then
notes = mw.html.create('div')
:addClass('ombox-content')
:css({
['text-align'] = 'left',
['max-height'] = '5.5em',
['overflow'] = 'scroll',
['padding'] = '0.25em',
['margin'] = '0.25em',
['border-style'] = 'dashed',
})
:newline()
:wikitext(args.notes .. cat)
:newline()
:allDone()
end
return messageBox.main('ombox', {
type = 'content',
image = '[[File:Ambox important.svg|24px]]',
style = 'box-sizing:border-box;margin:-0.93em auto 0.0em;text-align:center;width:100%;',
textstyle = 'font-size:93%;text-decoration:none;',
text = text .. tostring(notes),
})
end
function p.index_talk_remarks(frame)
local args = {}
for k, v in pairs(frame.args) do args[k] = v end
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
return p._index_talk_remarks(args)
end
-- Language resolution
-- Resolves the display language string and emits language-related tracking
-- categories onto `html`. Returns the display string, or nil if unavailable.
local function resolve_language(args, item, html)
local displayLang = nil
local languageCount = 0
if item then
local languages = item:formatPropertyValues(
'P407', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value
if languages and mw.text.trim(languages) ~= '' then
displayLang = languages
for language in languages:gmatch('([^,]+)') do
language = mw.text.trim(language)
if language ~= '' then
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam ' .. language
))
end
end
end
end
if not displayLang and args.language then
local displayLangs = {}
for _, l in ipairs(mw.text.split(args.language, ',%s*', false)) do
local lang = mw.text.trim(l)
if lang ~= '' then
local langName = ISO_639.language_name(lang, lang)
table.insert(displayLangs, langName)
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam bahasa ' .. langName
))
end
end
if #displayLangs > 0 then
displayLang = table.concat(displayLangs, ', ')
end
end
if displayLang then
html:wikitext(construct_cat('Karya dengan maklumat bahasa'))
if languageCount > 1 then
html:wikitext(construct_cat('Laman indeks karya yang asal dalam pelbagai bahasa'))
end
else
html:wikitext(construct_cat('Laman indeks karya tanpa maklumat bahasa'))
end
return displayLang
end
-- Metadata table
-- File formats that should render as a link to the index file page.
local LINKABLE_SOURCES = {
djvu=true, pdf=true, png=true, gif=true,
tif=true, ogg=true, ogv=true, webm=true,
}
local function build_metadata(args, item, html)
local t = mw.html.create('table'):attr('id', 'ws-index-metadata')
-- Title
if args.title then
local titleContent
if item then
titleContent = withWikidataLink(args.title)
elseif args.title:find('%[%[') then
titleContent = args.title
else
titleContent = '[[' .. args.title .. ']]'
end
t:node(construct_field('title', titleContent))
else
mw.addWarning('Anda perlu isi medan tajuk borang.')
end
-- Subtitle
add_field(t, html, 'subtitle', withWikidataLink(args.subtitle))
-- Language (complex; categories emitted inside resolve_language)
add_field(t, html, 'language', resolve_language(args, item, html))
-- Simple bibliographic fields
add_field(t, html, 'volume',
args.volume,
'Karya dengan maklumat nombor jilid',
'Karya tanpa maklumat nombor jilid')
add_field(t, html, 'edition',
args.edition,
'Karya dengan maklumat edisi',
'Karya tanpa maklumat edisi')
-- Author (also emits per-author categories from Wikidata)
if args.author then
t:node(construct_field('author', format_person(args.author, item)))
html:wikitext(construct_cat('Karya dengan maklumat pengarang'))
if item then
local authors = item:formatPropertyValues(
'P50', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value or ''
for author in authors:gmatch('([^,]+)') do
html:wikitext(construct_cat('Karya ' .. mw.text.trim(author)))
end
end
else
html:wikitext(construct_cat('Karya tanpa maklumat pengarang'))
end
-- Contributor fields
add_field(t, html, 'translator',
args.translator and format_person(args.translator, item),
'Karya dengan maklumat penterjemah',
'Karya tanpa maklumat penterjemah')
add_field(t, html, 'editor',
args.editor and format_person(args.editor, item),
'Karya dengan maklumat penyunting',
'Karya tanpa maklumat penyunting')
add_field(t, html, 'illustrator',
args.illustrator and withWikidataLink(args.illustrator),
'Karya dengan maklumat pengilustrasi',
'Karya tanpa maklumat pengilustrasi')
add_field(t, html, 'publisher',
args.publisher and withWikidataLink(args.publisher),
'Karya dengan maklumat penerbit',
'Karya tanpa maklumat penerbit')
-- Address / Published-in (mutually exclusive)
if args.address then
t:node(construct_field('address', withWikidataLink(args.address)))
html:wikitext(construct_cat('Karya dengan maklumat alamat'))
elseif args.publishedin then
t:node(construct_field('publishedin', withWikidataLink(args.publishedin)))
html:wikitext(construct_cat('Karya dengan maklumat alamat penerbitan'))
else
html:wikitext(construct_cat('Karya tanpa maklumat alamat penerbitan'))
end
-- Year / Inception (mutually exclusive)
if args.year then
t:node(construct_field('year', withWikidataLink(args.year)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh'))
html:wikitext(construct_cat('Karya tahun ' .. args.year))
elseif args.inception then
t:node(construct_field('inception', withWikidataLink(args.inception)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh terawal'))
else
html:wikitext(construct_cat('Karya tanpa maklumat tarikh'))
end
add_field(t, html, 'printer',
args.printer and withWikidataLink(args.printer),
'Karya dengan maklumat pencetak',
'Karya tanpa maklumat pencetak')
-- Source (linkable formats get a file-page link)
local src = args.source
t:node(construct_field('source',
src and LINKABLE_SOURCES[src]
and '[[:Fail:' .. mw.title.getCurrentTitle().text .. '|' .. src .. ']]'
or src
))
-- Progress & transclusion status
local progress_data = construct_status_field(args, { key = 'progress', config_key = 'status' })
local transclusion_data = construct_status_field(args, { key = 'transclusion' })
t:node(progress_data.row); html:wikitext(progress_data.cat)
t:node(transclusion_data.row); html:wikitext(transclusion_data.cat)
-- Validation date
local vdate = args.validation_date
if vdate then
local vcat = cfg.validation_cats.dated(vdate)
t:node(construct_field('validation_date', construct_cat_link(vcat, vdate)))
html:wikitext(construct_cat(vcat))
elseif args.progress == 'T' then
html:wikitext(construct_cat(cfg.validation_cats.undated))
end
-- Standard identifiers
for _, id in ipairs({ 'isbn', 'oclc', 'lccn', 'ark', 'doi' }) do
local val = args[id]
if val then
local link_fn = cfg.url_gens[id]
t:node(construct_field(id, link_fn and link_fn(val, val) or val))
end
end
add_field(t, html, 'volumes', args.volumes)
return t
end
-- Cover image
--[=[
Decision tree (evaluated in order):
1. Full [[...]] wikilink spec supplied → use as-is
2. Bare filename (has extension) → strip namespace prefix, rewrap
3. Audiovisual timestamp string → treat as thumbtime= value (→ case 5)
4. Multipage (DjVu/PDF) + file exists → page= thumbnail
5. Audiovisual + file exists → thumbtime= thumbnail
6. Any other type + file exists → plain file link
7. File does not exist → placeholder + missing category
--]=]
local function build_cover(args)
local image_number = tonumber(args.image)
-- Treat a bare timestamp string (e.g. "83" or "1:23") as a thumbtime value.
if args.image and not image_number
and args.source_type == 'audiovisual'
and mw.ustring.match(args.image, '^%d+[%d:]*$') then
image_number = args.image
end
local image_spec
local cats = {}
if not image_number and args.image and mw.ustring.find(args.image, '^%[%[') then
-- Case 1: full wikilink spec
image_spec = args.image
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif not image_number and args.image and mw.ustring.find(args.image, '%.%w+$') then
-- Case 2: bare filename — strip any recognised File namespace prefix
local image_name = args.image
local file_ns = mw.site.namespaces[6]
local prefixes = { file_ns.name, file_ns.canonicalName }
for _, alias in ipairs(file_ns.aliases) do
table.insert(prefixes, alias)
end
for _, prefix in ipairs(prefixes) do
image_name = mw.ustring.gsub(image_name, '^' .. prefix .. ':', '')
image_name = mw.ustring.gsub(image_name, '^' .. prefix:lower() .. ':', '')
end
image_spec = '[[' .. mw.title.makeTitle('Fail', image_name).prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif args.source_type == 'multipage' and args.file_exists then
-- Case 4: DjVu / PDF page thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|page=' .. (image_number or 1)
.. '|class=ws-cover]]'
elseif args.source_type == 'audiovisual' and args.file_exists then
-- Case 5: audio / video timestamp thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|thumbtime=' .. (image_number or 0)
.. '|class=ws-cover]]'
elseif args.file_exists then
-- Case 6: image or unknown type
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
else
-- Case 7: file missing — fall back to placeholder
local image_link = args.fileTitle.prefixedText
if not mw.ustring.find(args.fileTitle.rootText, '^.*%.%w+') then
image_link = 'Special:Upload'
end
image_spec = '[[' .. cfg.cover.image
.. '|' .. cfg.cover.width
.. '|link=' .. image_link
.. '|class=ws-cover]]'
table.insert(cats, construct_cat(cfg.cover_cats.missing))
end
return image_spec .. table.concat(cats)
end
-- Argument setup
-- Resolves all derived values and performs every expensive DB lookup exactly
-- once. Anything that touches the DB (file.exists, title.exists) lives here
-- and nowhere else, making the cost immediately visible to maintainers.
local function process_args(args)
-- Apply config defaults for any args not supplied by the template.
for k, v in pairs(cfg.defaults or {}) do
if args[k] == nil then args[k] = v end
end
-- Allow pageTitle to be pre-set (e.g. from a sandbox or test harness).
-- In normal template rendering it is always nil, so getCurrentTitle() is used.
args.pageTitle = (args.pageTitle and mw.title.new(args.pageTitle))
or mw.title.getCurrentTitle()
args.talkPageTitle = args.pageTitle.talkPageTitle
args.fileTitle = mw.title.makeTitle('Fail', args.pageTitle.rootText)
args.source_type = cfg.cover_cats.file_types[args.source]
args.file_exists = args.fileTitle.file.exists -- expensive: DB lookup
args.talk_exists = args.talkPageTitle.exists -- expensive: DB lookup
return args
end
-- Main entry point
local INDICATOR_ORDER = { 'pagegame', 'purge', 'book2scroll', 'bookreader', 'validated' }
local function indexTemplate(frame)
local styles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modul:Index template/styles.css' },
}
local data = (require 'Modul:Index_template/data').indexDataWithWikidata(frame)
local args, item = data.args, data.item
args = process_args(args)
-- Sort index pages correctly in categories (falls back to page title).
local sortkey = mw.getCurrentFrame():callParserFunction(
'DEFAULTSORT', { args.pageTitle.text }
)
-- Scan the talk page for formatting notes unless notes were supplied directly.
local talkremarks = ''
local talk_page_exists = args.talk_exists
if talk_page_exists and not args.notes then
local content = args.talkPageTitle.content
for _, keyword in ipairs(cfg.talkremarks.keywords) do
local pattern = keyword.alone
and '==( *' .. keyword.pattern .. ' *)=='
or '==([^=%n]*' .. keyword.pattern .. '[^=%n]*)=='
local section = mw.ustring.match(content, pattern)
if section then
args.notes = mw.getCurrentFrame():callParserFunction(
'#lsth',
args.talkPageTitle.prefixedText,
mw.text.trim(section)
)
break
end
end
end
if talk_page_exists then
talkremarks = p._index_talk_remarks(args)
end
local html = mw.html.create()
-- Wikidata indicator
if item then
html:wikitext('[[Kategori:Karya dengan ID Wikidata]]')
html:wikitext(
'<indicator name="wikidata">[[File:Wikidata.svg|20px|ID Wikidata|link=d:'
.. item.id .. ']]</indicator>'
)
else
html:wikitext('[[Kategori:Karya tanpa ID Wikidata]]')
end
-- Tool indicators
local indicators_cfg = require('Modul:Index template/indicators')
for _, key in ipairs(INDICATOR_ORDER) do
html:wikitext(construct_indicator(args, indicators_cfg[key]))
end
local metadataTable = build_metadata(args, item, html)
local coverImage = build_cover(args)
-- Outer layout: [cover + metadata + pagelist] | [remarks]
local outerRow = html:tag('table')
:attr('id', 'ws-index-container')
:tag('tr')
outerRow:tag('td')
:attr('id', 'ws-index-main-cell')
:tag('table')
:attr('id', 'ws-index-main-table')
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-cover-container')
:wikitext(coverImage)
:done()
:node(metadataTable)
:done()
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-pagelist-container')
:addClass('mw-collapsible')
:tag('em'):wikitext(cfg.pagelist.pages.txt):done()
:wikitext(' ')
:tag('span')
:attr('id', 'ws-index-pagelist-legend')
:wikitext(cfg.pagelist.legend.txt)
:done()
:tag('div')
:attr('id', 'ws-index-pagelist')
:addClass('index-pagelist mw-collapsible-content')
:newline()
:wikitext(args.pages and mw.text.trim(args.pages))
:newline()
if args.remarks then
outerRow:tag('td')
:attr('id', 'ws-index-remarks')
:newline()
:wikitext(frame:preprocess(args.remarks))
else
outerRow:tag('td'):attr('id', 'ws-index-remarks-empty')
end
-- Notes block
if args.notes then
html:tag('div'):attr('id', 'ws-index-notes'):wikitext(args.notes)
end
-- Tracking categories
if cfg.type_cats[args.type] then
html:wikitext(construct_cat(cfg.type_cats[args.type]))
end
if cfg.source_cats[args.source] then
html:wikitext(construct_cat(cfg.source_cats[args.source]))
elseif args.source ~= 'lain-lain' then
html:wikitext(construct_cat('Indeks fail format lain'))
end
html:wikitext(construct_cat('Indeks'))
if not args.remarks then
html:wikitext(construct_cat('Laman berindeks'))
end
return talkremarks .. styles .. tostring(html) .. sortkey
end
function p.indexTemplate(frame)
return indexTemplate(frame)
end
return p
emklx555ci0ze4sluqj3fn8kega398e
22823
22820
2026-04-15T04:33:43Z
Hakimi97
9
Merge Modul:Index template/indicators into Modul:Index template/config
22823
Scribunto
text/plain
--[=[
Latest update: 15th April 2026
This is a module to implement logic for [[MediaWiki:Proofreadpage index template]],
to render the book/index metadata panel for Malay Wikisource index pages.
]=]
local ISO_639 = require('Modul:ISO 639')
local messageBox = require('Module:Message box')
local category_handler = require('Module:Category handler')._main
local cfg = require('Modul:Index template/config')
-- Low-level markup helpers
local function construct_cat(cat)
return '[[Kategori:' .. cat .. ']]'
end
local function construct_cat_link(cat, text)
return '[[:Kategori:' .. cat .. '|' .. (text or cat) .. ']]'
end
-- Builds a single labelled metadata row.
local function construct_field(id, content)
if id == nil or content == nil then return nil end
if not cfg.headings[id] then error(cfg.missing_heading_id(id)) end
return mw.html.create('tr')
:attr('id', 'ws-index-' .. id .. '-row')
:addClass('ws-index-row')
:tag('th')
:attr('scope', 'row')
:attr('id', 'ws-index-' .. id .. '-label')
:addClass('ws-index-label')
:wikitext(cfg.headings[id].txt)
:done()
:tag('td')
:attr('id', 'ws-index-' .. id .. '-value')
:addClass('ws-index-value')
:wikitext(content)
:allDone()
end
-- Conditionally adds a metadata row and the appropriate tracking category.
-- If `content` is truthy the row is added plus `with_cat` (if given).
-- Otherwise only `without_cat` is emitted (if given).
local function add_field(tbl, html, id, content, with_cat, without_cat)
if content then
tbl:node(construct_field(id, content))
if with_cat then html:wikitext(construct_cat(with_cat)) end
elseif without_cat then
html:wikitext(construct_cat(without_cat))
end
end
-- Wikidata link helpers
local function addWikidataToLink(page, label, category)
local title = mw.title.new(page)
if title == nil then
return '[[' .. page .. '|' .. label .. ']]'
end
if title.isRedirect then title = title.redirectTarget end
local tag = mw.html.create('span')
local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
tag:wikitext('[[' .. page .. '|' .. label .. ']]')
if itemId then
tag:wikitext(
' [[Image:Wikidata.svg|10px|link=d:' .. itemId .. '|Lihat maklumat di Wikidata]]'
)
if category then tag:wikitext('[[Kategori:' .. category .. ']]') end
end
return tostring(tag)
end
-- Walks wikilinks inside `wikitext` and augments each with a Wikidata icon
-- when the linked page has a Wikidata entity.
local function withWikidataLink(wikitext, category)
if wikitext == nil then return nil end
-- Try bare [[Page]] links first …
local result = mw.ustring.gsub(wikitext, '%[%[([^|%]]*)%]%]', function(page)
return addWikidataToLink(page, mw.ustring.gsub(page, '%.*/', ''), category)
end)
if result ~= wikitext then return result end
-- … then [[Page|Label]] links.
return mw.ustring.gsub(wikitext, '%[%[([^|]*)|([^|%]]*)%]%]', function(page, link)
return addWikidataToLink(page, link, category)
end)
end
-- Formats a contributor field (author / translator / editor).
-- With a Wikidata item: augments links with Wikidata icons.
-- Without: wraps bare (non-wikilinked) names in {{Al|}}.
local function format_person(value, item)
if item then return withWikidataLink(value) end
if value:find('%[%[') then return value end
return '{{Al|' .. value .. '}}'
end
-- Progress / transclusion status rows
local function construct_status_field(args, statusArgs)
local key = statusArgs.key
local config_key = statusArgs.config_key or key
local index_status = args[key] or '_missing'
local sd = cfg[config_key][index_status] or cfg[config_key]['_default']
local txt = sd.txt
if type(txt) == 'function' then txt = txt(index_status) end
local display = sd.error
and ('<span class="error">' .. txt .. '</span>')
or construct_cat_link(sd.cat, txt)
return {
row = construct_field(key, display),
cat = construct_cat(sd.cat),
}
end
-- Indicator builder
-- Builds one <indicator> tag from an indicator config entry.
-- `link` and `caption` may be plain strings or functions called with `args`.
-- An optional `include` predicate (also called with `args`) gates rendering;
-- defaults to always-show when absent.
local function construct_indicator(args, iData)
local include = iData.include or cfg.indicator_defaults.include
if not include(args) then return '' end
local parts = { iData.image, iData.width or cfg.indicator_defaults.width }
if iData.alt then table.insert(parts, 'alt=' .. iData.alt) end
local link = iData.link
if type(link) == 'function' then link = link(args) end
if link then table.insert(parts, 'link=' .. link) end
local caption = iData.caption
if type(caption) == 'function' then caption = caption(args) end
if caption then table.insert(parts, caption) end
return mw.getCurrentFrame():extensionTag{
name = 'indicator',
content = '[[' .. table.concat(parts, '|') .. ']]',
args = { name = iData.name },
}
end
-- Talk-page remarks
local p = {}
function p._index_talk_remarks(args)
if not args.talkPageTitle then
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
end
local text = cfg.talkremarks.text(args)
local cat = category_handler({ construct_cat(cfg.talkremarks.cat) }) or ''
local notes = ''
if args.notes then
notes = mw.html.create('div')
:addClass('ombox-content')
:css({
['text-align'] = 'left',
['max-height'] = '5.5em',
['overflow'] = 'scroll',
['padding'] = '0.25em',
['margin'] = '0.25em',
['border-style'] = 'dashed',
})
:newline()
:wikitext(args.notes .. cat)
:newline()
:allDone()
end
return messageBox.main('ombox', {
type = 'content',
image = '[[File:Ambox important.svg|24px]]',
style = 'box-sizing:border-box;margin:-0.93em auto 0.0em;text-align:center;width:100%;',
textstyle = 'font-size:93%;text-decoration:none;',
text = text .. tostring(notes),
})
end
function p.index_talk_remarks(frame)
local args = {}
for k, v in pairs(frame.args) do args[k] = v end
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
return p._index_talk_remarks(args)
end
-- Language resolution
-- Resolves the display language string and emits language-related tracking
-- categories onto `html`. Returns the display string, or nil if unavailable.
local function resolve_language(args, item, html)
local displayLang = nil
local languageCount = 0
if item then
local languages = item:formatPropertyValues(
'P407', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value
if languages and mw.text.trim(languages) ~= '' then
displayLang = languages
for language in languages:gmatch('([^,]+)') do
language = mw.text.trim(language)
if language ~= '' then
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam ' .. language
))
end
end
end
end
if not displayLang and args.language then
local displayLangs = {}
for _, l in ipairs(mw.text.split(args.language, ',%s*', false)) do
local lang = mw.text.trim(l)
if lang ~= '' then
local langName = ISO_639.language_name(lang, lang)
table.insert(displayLangs, langName)
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam bahasa ' .. langName
))
end
end
if #displayLangs > 0 then
displayLang = table.concat(displayLangs, ', ')
end
end
if displayLang then
html:wikitext(construct_cat('Karya dengan maklumat bahasa'))
if languageCount > 1 then
html:wikitext(construct_cat('Laman indeks karya yang asal dalam pelbagai bahasa'))
end
else
html:wikitext(construct_cat('Laman indeks karya tanpa maklumat bahasa'))
end
return displayLang
end
-- Metadata table
-- File formats that should render as a link to the index file page.
local LINKABLE_SOURCES = {
djvu=true, pdf=true, png=true, gif=true,
tif=true, ogg=true, ogv=true, webm=true,
}
local function build_metadata(args, item, html)
local t = mw.html.create('table'):attr('id', 'ws-index-metadata')
-- Title
if args.title then
local titleContent
if item then
titleContent = withWikidataLink(args.title)
elseif args.title:find('%[%[') then
titleContent = args.title
else
titleContent = '[[' .. args.title .. ']]'
end
t:node(construct_field('title', titleContent))
else
mw.addWarning('Anda perlu isi medan tajuk borang.')
end
-- Subtitle
add_field(t, html, 'subtitle', withWikidataLink(args.subtitle))
-- Language (complex; categories emitted inside resolve_language)
add_field(t, html, 'language', resolve_language(args, item, html))
-- Simple bibliographic fields
add_field(t, html, 'volume',
args.volume,
'Karya dengan maklumat nombor jilid',
'Karya tanpa maklumat nombor jilid')
add_field(t, html, 'edition',
args.edition,
'Karya dengan maklumat edisi',
'Karya tanpa maklumat edisi')
-- Author (also emits per-author categories from Wikidata)
if args.author then
t:node(construct_field('author', format_person(args.author, item)))
html:wikitext(construct_cat('Karya dengan maklumat pengarang'))
if item then
local authors = item:formatPropertyValues(
'P50', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value or ''
for author in authors:gmatch('([^,]+)') do
html:wikitext(construct_cat('Karya ' .. mw.text.trim(author)))
end
end
else
html:wikitext(construct_cat('Karya tanpa maklumat pengarang'))
end
-- Contributor fields
add_field(t, html, 'translator',
args.translator and format_person(args.translator, item),
'Karya dengan maklumat penterjemah',
'Karya tanpa maklumat penterjemah')
add_field(t, html, 'editor',
args.editor and format_person(args.editor, item),
'Karya dengan maklumat penyunting',
'Karya tanpa maklumat penyunting')
add_field(t, html, 'illustrator',
args.illustrator and withWikidataLink(args.illustrator),
'Karya dengan maklumat pengilustrasi',
'Karya tanpa maklumat pengilustrasi')
add_field(t, html, 'publisher',
args.publisher and withWikidataLink(args.publisher),
'Karya dengan maklumat penerbit',
'Karya tanpa maklumat penerbit')
-- Address / Published-in (mutually exclusive)
if args.address then
t:node(construct_field('address', withWikidataLink(args.address)))
html:wikitext(construct_cat('Karya dengan maklumat alamat'))
elseif args.publishedin then
t:node(construct_field('publishedin', withWikidataLink(args.publishedin)))
html:wikitext(construct_cat('Karya dengan maklumat alamat penerbitan'))
else
html:wikitext(construct_cat('Karya tanpa maklumat alamat penerbitan'))
end
-- Year / Inception (mutually exclusive)
if args.year then
t:node(construct_field('year', withWikidataLink(args.year)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh'))
html:wikitext(construct_cat('Karya tahun ' .. args.year))
elseif args.inception then
t:node(construct_field('inception', withWikidataLink(args.inception)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh terawal'))
else
html:wikitext(construct_cat('Karya tanpa maklumat tarikh'))
end
add_field(t, html, 'printer',
args.printer and withWikidataLink(args.printer),
'Karya dengan maklumat pencetak',
'Karya tanpa maklumat pencetak')
-- Source (linkable formats get a file-page link)
local src = args.source
t:node(construct_field('source',
src and LINKABLE_SOURCES[src]
and '[[:Fail:' .. mw.title.getCurrentTitle().text .. '|' .. src .. ']]'
or src
))
-- Progress & transclusion status
local progress_data = construct_status_field(args, { key = 'progress', config_key = 'status' })
local transclusion_data = construct_status_field(args, { key = 'transclusion' })
t:node(progress_data.row); html:wikitext(progress_data.cat)
t:node(transclusion_data.row); html:wikitext(transclusion_data.cat)
-- Validation date
local vdate = args.validation_date
if vdate then
local vcat = cfg.validation_cats.dated(vdate)
t:node(construct_field('validation_date', construct_cat_link(vcat, vdate)))
html:wikitext(construct_cat(vcat))
elseif args.progress == 'T' then
html:wikitext(construct_cat(cfg.validation_cats.undated))
end
-- Standard identifiers
for _, id in ipairs({ 'isbn', 'oclc', 'lccn', 'ark', 'doi' }) do
local val = args[id]
if val then
local link_fn = cfg.url_gens[id]
t:node(construct_field(id, link_fn and link_fn(val, val) or val))
end
end
add_field(t, html, 'volumes', args.volumes)
return t
end
-- Cover image
--[=[
Decision tree (evaluated in order):
1. Full [[...]] wikilink spec supplied → use as-is
2. Bare filename (has extension) → strip namespace prefix, rewrap
3. Audiovisual timestamp string → treat as thumbtime= value (→ case 5)
4. Multipage (DjVu/PDF) + file exists → page= thumbnail
5. Audiovisual + file exists → thumbtime= thumbnail
6. Any other type + file exists → plain file link
7. File does not exist → placeholder + missing category
--]=]
local function build_cover(args)
local image_number = tonumber(args.image)
-- Treat a bare timestamp string (e.g. "83" or "1:23") as a thumbtime value.
if args.image and not image_number
and args.source_type == 'audiovisual'
and mw.ustring.match(args.image, '^%d+[%d:]*$') then
image_number = args.image
end
local image_spec
local cats = {}
if not image_number and args.image and mw.ustring.find(args.image, '^%[%[') then
-- Case 1: full wikilink spec
image_spec = args.image
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif not image_number and args.image and mw.ustring.find(args.image, '%.%w+$') then
-- Case 2: bare filename — strip any recognised File namespace prefix
local image_name = args.image
local file_ns = mw.site.namespaces[6]
local prefixes = { file_ns.name, file_ns.canonicalName }
for _, alias in ipairs(file_ns.aliases) do
table.insert(prefixes, alias)
end
for _, prefix in ipairs(prefixes) do
image_name = mw.ustring.gsub(image_name, '^' .. prefix .. ':', '')
image_name = mw.ustring.gsub(image_name, '^' .. prefix:lower() .. ':', '')
end
image_spec = '[[' .. mw.title.makeTitle('Fail', image_name).prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif args.source_type == 'multipage' and args.file_exists then
-- Case 4: DjVu / PDF page thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|page=' .. (image_number or 1)
.. '|class=ws-cover]]'
elseif args.source_type == 'audiovisual' and args.file_exists then
-- Case 5: audio / video timestamp thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|thumbtime=' .. (image_number or 0)
.. '|class=ws-cover]]'
elseif args.file_exists then
-- Case 6: image or unknown type
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
else
-- Case 7: file missing — fall back to placeholder
local image_link = args.fileTitle.prefixedText
if not mw.ustring.find(args.fileTitle.rootText, '^.*%.%w+') then
image_link = 'Special:Upload'
end
image_spec = '[[' .. cfg.cover.image
.. '|' .. cfg.cover.width
.. '|link=' .. image_link
.. '|class=ws-cover]]'
table.insert(cats, construct_cat(cfg.cover_cats.missing))
end
return image_spec .. table.concat(cats)
end
-- Argument setup
-- Resolves all derived values and performs every expensive DB lookup exactly
-- once. Anything that touches the DB (file.exists, title.exists) lives here
-- and nowhere else, making the cost immediately visible to maintainers.
local function process_args(args)
-- Apply config defaults for any args not supplied by the template.
for k, v in pairs(cfg.defaults or {}) do
if args[k] == nil then args[k] = v end
end
-- Allow pageTitle to be pre-set (e.g. from a sandbox or test harness).
-- In normal template rendering it is always nil, so getCurrentTitle() is used.
args.pageTitle = (args.pageTitle and mw.title.new(args.pageTitle))
or mw.title.getCurrentTitle()
args.talkPageTitle = args.pageTitle.talkPageTitle
args.fileTitle = mw.title.makeTitle('Fail', args.pageTitle.rootText)
args.source_type = cfg.cover_cats.file_types[args.source]
args.file_exists = args.fileTitle.file.exists -- expensive: DB lookup
args.talk_exists = args.talkPageTitle.exists -- expensive: DB lookup
return args
end
-- Main entry point
local function indexTemplate(frame)
local styles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modul:Index template/styles.css' },
}
local data = (require 'Modul:Index_template/data').indexDataWithWikidata(frame)
local args, item = data.args, data.item
args = process_args(args)
-- Sort index pages correctly in categories (falls back to page title).
local sortkey = mw.getCurrentFrame():callParserFunction(
'DEFAULTSORT', { args.pageTitle.text }
)
-- Scan the talk page for formatting notes unless notes were supplied directly.
local talkremarks = ''
local talk_page_exists = args.talk_exists
if talk_page_exists and not args.notes then
local content = args.talkPageTitle.content
for _, keyword in ipairs(cfg.talkremarks.keywords) do
local pattern = keyword.alone
and '==( *' .. keyword.pattern .. ' *)=='
or '==([^=%n]*' .. keyword.pattern .. '[^=%n]*)=='
local section = mw.ustring.match(content, pattern)
if section then
args.notes = mw.getCurrentFrame():callParserFunction(
'#lsth',
args.talkPageTitle.prefixedText,
mw.text.trim(section)
)
break
end
end
end
if talk_page_exists then
talkremarks = p._index_talk_remarks(args)
end
local html = mw.html.create()
-- Wikidata indicator
if item then
html:wikitext('[[Kategori:Karya dengan ID Wikidata]]')
html:wikitext(
'<indicator name="wikidata">[[File:Wikidata.svg|20px|ID Wikidata|link=d:'
.. item.id .. ']]</indicator>'
)
else
html:wikitext('[[Kategori:Karya tanpa ID Wikidata]]')
end
-- Tool indicators
for _, v in ipairs(cfg.indicators) do
html:wikitext(construct_indicator(args, v))
end
local metadataTable = build_metadata(args, item, html)
local coverImage = build_cover(args)
-- Outer layout: [cover + metadata + pagelist] | [remarks]
local outerRow = html:tag('table')
:attr('id', 'ws-index-container')
:tag('tr')
outerRow:tag('td')
:attr('id', 'ws-index-main-cell')
:tag('table')
:attr('id', 'ws-index-main-table')
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-cover-container')
:wikitext(coverImage)
:done()
:node(metadataTable)
:done()
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-pagelist-container')
:addClass('mw-collapsible')
:tag('em'):wikitext(cfg.pagelist.pages.txt):done()
:wikitext(' ')
:tag('span')
:attr('id', 'ws-index-pagelist-legend')
:wikitext(cfg.pagelist.legend.txt)
:done()
:tag('div')
:attr('id', 'ws-index-pagelist')
:addClass('index-pagelist mw-collapsible-content')
:newline()
:wikitext(args.pages and mw.text.trim(args.pages))
:newline()
if args.remarks then
outerRow:tag('td')
:attr('id', 'ws-index-remarks')
:newline()
:wikitext(frame:preprocess(args.remarks))
else
outerRow:tag('td'):attr('id', 'ws-index-remarks-empty')
end
-- Notes block
if args.notes then
html:tag('div'):attr('id', 'ws-index-notes'):wikitext(args.notes)
end
-- Tracking categories
if cfg.type_cats[args.type] then
html:wikitext(construct_cat(cfg.type_cats[args.type]))
end
if cfg.source_cats[args.source] then
html:wikitext(construct_cat(cfg.source_cats[args.source]))
elseif args.source ~= 'lain-lain' then
html:wikitext(construct_cat('Indeks fail format lain'))
end
html:wikitext(construct_cat('Indeks'))
if not args.remarks then
html:wikitext(construct_cat('Laman berindeks'))
end
return talkremarks .. styles .. tostring(html) .. sortkey
end
function p.indexTemplate(frame)
return indexTemplate(frame)
end
return p
c7xm26fd2fd5z7nqa8bzsbr6oojxnkv
22828
22823
2026-04-15T05:08:52Z
Hakimi97
9
Code consolidation
22828
Scribunto
text/plain
--[=[
Latest update: 15th April 2026
This is a module to implement logic for [[MediaWiki:Proofreadpage index template]],
to render the book/index metadata panel for Malay Wikisource index pages.
]=]
local ISO_639 = require('Modul:ISO 639')
local messageBox = require('Module:Message box')
local category_handler = require('Module:Category handler')._main
local cfg = require('Modul:Index template/config')
-- Low-level markup helpers
local function construct_cat(cat)
return '[[Kategori:' .. cat .. ']]'
end
local function construct_cat_link(cat, text)
return '[[:Kategori:' .. cat .. '|' .. (text or cat) .. ']]'
end
-- Builds a single labelled metadata row.
local function construct_field(id, content)
if id == nil or content == nil then return nil end
if not cfg.headings[id] then error(cfg.missing_heading_id(id)) end
return mw.html.create('tr')
:attr('id', 'ws-index-' .. id .. '-row')
:addClass('ws-index-row')
:tag('th')
:attr('scope', 'row')
:attr('id', 'ws-index-' .. id .. '-label')
:addClass('ws-index-label')
:wikitext(cfg.headings[id].txt)
:done()
:tag('td')
:attr('id', 'ws-index-' .. id .. '-value')
:addClass('ws-index-value')
:wikitext(content)
:allDone()
end
-- Conditionally adds a metadata row and the appropriate tracking category.
-- If `content` is truthy the row is added plus `with_cat` (if given).
-- Otherwise only `without_cat` is emitted (if given).
local function add_field(tbl, html, id, content, with_cat, without_cat)
if content then
tbl:node(construct_field(id, content))
if with_cat then html:wikitext(construct_cat(with_cat)) end
elseif without_cat then
html:wikitext(construct_cat(without_cat))
end
end
-- Wikidata link helpers
local function addWikidataToLink(page, label, category)
local title = mw.title.new(page)
if title == nil then
return '[[' .. page .. '|' .. label .. ']]'
end
if title.isRedirect then title = title.redirectTarget end
local tag = mw.html.create('span')
local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
tag:wikitext('[[' .. page .. '|' .. label .. ']]')
if itemId then
tag:wikitext(
' [[Image:Wikidata.svg|10px|link=d:' .. itemId .. '|Lihat maklumat di Wikidata]]'
)
if category then tag:wikitext('[[Kategori:' .. category .. ']]') end
end
return tostring(tag)
end
-- Walks wikilinks inside `wikitext` and augments each with a Wikidata icon
-- when the linked page has a Wikidata entity.
local function withWikidataLink(wikitext, category)
if wikitext == nil then return nil end
-- Try bare [[Page]] links first …
local result = mw.ustring.gsub(wikitext, '%[%[([^|%]]*)%]%]', function(page)
return addWikidataToLink(page, mw.ustring.gsub(page, '%.*/', ''), category)
end)
if result ~= wikitext then return result end
-- … then [[Page|Label]] links.
return mw.ustring.gsub(wikitext, '%[%[([^|]*)|([^|%]]*)%]%]', function(page, link)
return addWikidataToLink(page, link, category)
end)
end
-- Formats a contributor field (author / translator / editor).
-- With a Wikidata item: augments links with Wikidata icons.
-- Without: wraps bare (non-wikilinked) names in {{Al|}}.
local function format_person(value, item)
if item then return withWikidataLink(value) end
if value:find('%[%[') then return value end
return '{{Al|' .. value .. '}}'
end
-- Progress / transclusion status rows
local function construct_status_field(args, statusArgs)
local key = statusArgs.key
local config_key = statusArgs.config_key or key
local index_status = args[key] or '_missing'
local sd = cfg[config_key][index_status] or cfg[config_key]['_default']
local txt = sd.txt
if type(txt) == 'function' then txt = txt(index_status) end
local display = sd.error
and ('<span class="error">' .. txt .. '</span>')
or construct_cat_link(sd.cat, txt)
return {
row = construct_field(key, display),
cat = construct_cat(sd.cat),
}
end
-- Indicator builder
-- Builds one <indicator> tag from an indicator config entry.
-- `link` and `caption` may be plain strings or functions called with `args`.
-- An optional `include` predicate (also called with `args`) gates rendering;
-- defaults to always-show when absent.
local function construct_indicator(args, iData)
local include = iData.include or cfg.indicator_defaults.include
if not include(args) then return '' end
local parts = { iData.image, iData.width or cfg.indicator_defaults.width }
if iData.alt then table.insert(parts, 'alt=' .. iData.alt) end
local link = iData.link
if type(link) == 'function' then link = link(args) end
if link then table.insert(parts, 'link=' .. link) end
local caption = iData.caption
if type(caption) == 'function' then caption = caption(args) end
if caption then table.insert(parts, caption) end
return mw.getCurrentFrame():extensionTag{
name = 'indicator',
content = '[[' .. table.concat(parts, '|') .. ']]',
args = { name = iData.name },
}
end
-- Talk-page remarks
local p = {}
function p._index_talk_remarks(args)
if not args.talkPageTitle then
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
end
local text = cfg.talkremarks.text(args)
local cat = category_handler({ construct_cat(cfg.talkremarks.cat) }) or ''
local notes = ''
if args.notes then
notes = mw.html.create('div')
:addClass('ombox-content')
:css({
['text-align'] = 'left',
['max-height'] = '5.5em',
['overflow'] = 'scroll',
['padding'] = '0.25em',
['margin'] = '0.25em',
['border-style'] = 'dashed',
})
:newline()
:wikitext(args.notes .. cat)
:newline()
:allDone()
end
return messageBox.main('ombox', {
type = 'content',
image = '[[File:Ambox important.svg|24px]]',
style = 'box-sizing:border-box;margin:-0.93em auto 0.0em;text-align:center;width:100%;',
textstyle = 'font-size:93%;text-decoration:none;',
text = text .. tostring(notes),
})
end
function p.index_talk_remarks(frame)
local args = {}
for k, v in pairs(frame.args) do args[k] = v end
args.talkPageTitle = mw.title.getCurrentTitle().talkPageTitle
return p._index_talk_remarks(args)
end
-- Language resolution
-- Resolves the display language string and emits language-related tracking
-- categories onto `html`. Returns the display string, or nil if unavailable.
local function resolve_language(args, item, html)
local displayLang = nil
local languageCount = 0
if item then
local languages = item:formatPropertyValues(
'P407', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value
if languages and mw.text.trim(languages) ~= '' then
displayLang = languages
for language in languages:gmatch('([^,]+)') do
language = mw.text.trim(language)
if language ~= '' then
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam ' .. language
))
end
end
end
end
if not displayLang and args.language then
local displayLangs = {}
for _, l in ipairs(mw.text.split(args.language, ',%s*', false)) do
local lang = mw.text.trim(l)
if lang ~= '' then
local langName = ISO_639.language_name(lang, lang)
table.insert(displayLangs, langName)
languageCount = languageCount + 1
html:wikitext(construct_cat(
'Laman indeks karya yang asal dalam bahasa ' .. langName
))
end
end
if #displayLangs > 0 then
displayLang = table.concat(displayLangs, ', ')
end
end
if displayLang then
html:wikitext(construct_cat('Karya dengan maklumat bahasa'))
if languageCount > 1 then
html:wikitext(construct_cat('Laman indeks karya yang asal dalam pelbagai bahasa'))
end
else
html:wikitext(construct_cat('Laman indeks karya tanpa maklumat bahasa'))
end
return displayLang
end
-- Metadata table
local function build_metadata(args, item, html)
local t = mw.html.create('table'):attr('id', 'ws-index-metadata')
-- Title
if args.title then
local titleContent
if item then
titleContent = withWikidataLink(args.title)
elseif args.title:find('%[%[') then
titleContent = args.title
else
titleContent = '[[' .. args.title .. ']]'
end
t:node(construct_field('title', titleContent))
else
mw.addWarning('Anda perlu isi medan tajuk borang.')
end
-- Subtitle
add_field(t, html, 'subtitle', withWikidataLink(args.subtitle))
-- Language (complex; categories emitted inside resolve_language)
add_field(t, html, 'language', resolve_language(args, item, html))
-- Simple bibliographic fields
add_field(t, html, 'volume',
args.volume,
'Karya dengan maklumat nombor jilid',
'Karya tanpa maklumat nombor jilid')
add_field(t, html, 'edition',
args.edition,
'Karya dengan maklumat edisi',
'Karya tanpa maklumat edisi')
-- Author (also emits per-author categories from Wikidata)
if args.author then
t:node(construct_field('author', format_person(args.author, item)))
html:wikitext(construct_cat('Karya dengan maklumat pengarang'))
if item then
local authors = item:formatPropertyValues(
'P50', { mw.wikibase.entity.claimRanks.RANK_NORMAL }
).value or ''
for author in authors:gmatch('([^,]+)') do
html:wikitext(construct_cat('Karya ' .. mw.text.trim(author)))
end
end
else
html:wikitext(construct_cat('Karya tanpa maklumat pengarang'))
end
-- Contributor fields
add_field(t, html, 'translator',
args.translator and format_person(args.translator, item),
'Karya dengan maklumat penterjemah',
'Karya tanpa maklumat penterjemah')
add_field(t, html, 'editor',
args.editor and format_person(args.editor, item),
'Karya dengan maklumat penyunting',
'Karya tanpa maklumat penyunting')
add_field(t, html, 'illustrator',
args.illustrator and withWikidataLink(args.illustrator),
'Karya dengan maklumat pengilustrasi',
'Karya tanpa maklumat pengilustrasi')
add_field(t, html, 'publisher',
args.publisher and withWikidataLink(args.publisher),
'Karya dengan maklumat penerbit',
'Karya tanpa maklumat penerbit')
-- Address / Published-in (mutually exclusive)
if args.address then
t:node(construct_field('address', withWikidataLink(args.address)))
html:wikitext(construct_cat('Karya dengan maklumat alamat'))
elseif args.publishedin then
t:node(construct_field('publishedin', withWikidataLink(args.publishedin)))
html:wikitext(construct_cat('Karya dengan maklumat alamat penerbitan'))
else
html:wikitext(construct_cat('Karya tanpa maklumat alamat penerbitan'))
end
-- Year / Inception (mutually exclusive)
if args.year then
t:node(construct_field('year', withWikidataLink(args.year)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh'))
html:wikitext(construct_cat('Karya tahun ' .. args.year))
elseif args.inception then
t:node(construct_field('inception', withWikidataLink(args.inception)))
html:wikitext(construct_cat('Karya dengan maklumat tarikh terawal'))
else
html:wikitext(construct_cat('Karya tanpa maklumat tarikh'))
end
add_field(t, html, 'printer',
args.printer and withWikidataLink(args.printer),
'Karya dengan maklumat pencetak',
'Karya tanpa maklumat pencetak')
-- Source (linkable formats get a file-page link)
local src = args.source
t:node(construct_field('source',
src and cfg.linkable_sources[src]
and '[[:Fail:' .. mw.title.getCurrentTitle().text .. '|' .. src .. ']]'
or src
))
-- Progress & transclusion status
local progress_data = construct_status_field(args, { key = 'progress', config_key = 'status' })
local transclusion_data = construct_status_field(args, { key = 'transclusion' })
t:node(progress_data.row); html:wikitext(progress_data.cat)
t:node(transclusion_data.row); html:wikitext(transclusion_data.cat)
-- Validation date
local vdate = args.validation_date
if vdate then
local vcat = cfg.validation_cats.dated(vdate)
t:node(construct_field('validation_date', construct_cat_link(vcat, vdate)))
html:wikitext(construct_cat(vcat))
elseif args.progress == 'T' then
html:wikitext(construct_cat(cfg.validation_cats.undated))
end
-- Standard identifiers
for _, id in ipairs({ 'isbn', 'oclc', 'lccn', 'ark', 'doi' }) do
local val = args[id]
if val then
local link_fn = cfg.url_gens[id]
t:node(construct_field(id, link_fn and link_fn(val, val) or val))
end
end
add_field(t, html, 'volumes', args.volumes)
return t
end
-- Cover image
--[=[
Decision tree (evaluated in order):
1. Full [[...]] wikilink spec supplied → use as-is
2. Bare filename (has extension) → strip namespace prefix, rewrap
3. Audiovisual timestamp string → treat as thumbtime= value (→ case 5)
4. Multipage (DjVu/PDF) + file exists → page= thumbnail
5. Audiovisual + file exists → thumbtime= thumbnail
6. Any other type + file exists → plain file link
7. File does not exist → placeholder + missing category
--]=]
local function build_cover(args)
local image_number = tonumber(args.image)
-- Treat a bare timestamp string (e.g. "83" or "1:23") as a thumbtime value.
if args.image and not image_number
and args.source_type == 'audiovisual'
and mw.ustring.match(args.image, '^%d+[%d:]*$') then
image_number = args.image
end
local image_spec
local cats = {}
if not image_number and args.image and mw.ustring.find(args.image, '^%[%[') then
-- Case 1: full wikilink spec
image_spec = args.image
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif not image_number and args.image and mw.ustring.find(args.image, '%.%w+$') then
-- Case 2: bare filename — strip any recognised File namespace prefix
local image_name = args.image
local file_ns = mw.site.namespaces[6]
local prefixes = { file_ns.name, file_ns.canonicalName }
for _, alias in ipairs(file_ns.aliases) do
table.insert(prefixes, alias)
end
for _, prefix in ipairs(prefixes) do
image_name = mw.ustring.gsub(image_name, '^' .. prefix .. ':', '')
image_name = mw.ustring.gsub(image_name, '^' .. prefix:lower() .. ':', '')
end
image_spec = '[[' .. mw.title.makeTitle('Fail', image_name).prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
if args.source_type ~= 'image' then
table.insert(cats, construct_cat(cfg.cover_cats.fullspec))
end
elseif args.source_type == 'multipage' and args.file_exists then
-- Case 4: DjVu / PDF page thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|page=' .. (image_number or 1)
.. '|class=ws-cover]]'
elseif args.source_type == 'audiovisual' and args.file_exists then
-- Case 5: audio / video timestamp thumbnail
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width
.. '|thumbtime=' .. (image_number or 0)
.. '|class=ws-cover]]'
elseif args.file_exists then
-- Case 6: image or unknown type
image_spec = '[[' .. args.fileTitle.prefixedText
.. '|' .. cfg.cover.width .. '|class=ws-cover]]'
else
-- Case 7: file missing — fall back to placeholder
local image_link = args.fileTitle.prefixedText
if not mw.ustring.find(args.fileTitle.rootText, '^.*%.%w+') then
image_link = 'Special:Upload'
end
image_spec = '[[' .. cfg.cover.image
.. '|' .. cfg.cover.width
.. '|link=' .. image_link
.. '|class=ws-cover]]'
table.insert(cats, construct_cat(cfg.cover_cats.missing))
end
return image_spec .. table.concat(cats)
end
-- Argument setup
-- Resolves all derived values and performs every expensive DB lookup exactly
-- once. Anything that touches the DB (file.exists, title.exists) lives here
-- and nowhere else, making the cost immediately visible to maintainers.
local function process_args(args)
-- Apply config defaults for any args not supplied by the template.
for k, v in pairs(cfg.defaults or {}) do
if args[k] == nil then args[k] = v end
end
-- Allow pageTitle to be pre-set (e.g. from a sandbox or test harness).
-- In normal template rendering it is always nil, so getCurrentTitle() is used.
args.pageTitle = (args.pageTitle and mw.title.new(args.pageTitle))
or mw.title.getCurrentTitle()
args.talkPageTitle = args.pageTitle.talkPageTitle
args.fileTitle = mw.title.makeTitle('Fail', args.pageTitle.rootText)
args.source_type = cfg.cover_cats.file_types[args.source]
args.file_exists = args.fileTitle.file.exists -- expensive: DB lookup
args.talk_exists = args.talkPageTitle.exists -- expensive: DB lookup
return args
end
-- Main entry point
local function indexTemplate(frame)
local styles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modul:Index template/styles.css' },
}
local data = (require 'Modul:Index_template/data').indexDataWithWikidata(frame)
local args, item = data.args, data.item
args = process_args(args)
-- Sort index pages correctly in categories (falls back to page title).
local sortkey = mw.getCurrentFrame():callParserFunction(
'DEFAULTSORT', { args.pageTitle.text }
)
-- Scan the talk page for formatting notes unless notes were supplied directly.
local talkremarks = ''
local talk_page_exists = args.talk_exists
if talk_page_exists and not args.notes then
local content = args.talkPageTitle.content
for _, keyword in ipairs(cfg.talkremarks.keywords) do
local pattern = keyword.alone
and '==( *' .. keyword.pattern .. ' *)=='
or '==([^=%n]*' .. keyword.pattern .. '[^=%n]*)=='
local section = mw.ustring.match(content, pattern)
if section then
args.notes = mw.getCurrentFrame():callParserFunction(
'#lsth',
args.talkPageTitle.prefixedText,
mw.text.trim(section)
)
break
end
end
end
if talk_page_exists then
talkremarks = p._index_talk_remarks(args)
end
local html = mw.html.create()
-- Wikidata indicator
if item then
html:wikitext('[[Kategori:Karya dengan ID Wikidata]]')
html:wikitext(
'<indicator name="wikidata">[[File:Wikidata.svg|20px|ID Wikidata|link=d:'
.. item.id .. ']]</indicator>'
)
else
html:wikitext('[[Kategori:Karya tanpa ID Wikidata]]')
end
-- Tool indicators
for _, v in ipairs(cfg.indicators) do
html:wikitext(construct_indicator(args, v))
end
local metadataTable = build_metadata(args, item, html)
local coverImage = build_cover(args)
-- Outer layout: [cover + metadata + pagelist] | [remarks]
local outerRow = html:tag('table')
:attr('id', 'ws-index-container')
:tag('tr')
outerRow:tag('td')
:attr('id', 'ws-index-main-cell')
:tag('table')
:attr('id', 'ws-index-main-table')
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-cover-container')
:wikitext(coverImage)
:done()
:node(metadataTable)
:done()
:tag('tr'):tag('td')
:tag('div')
:attr('id', 'ws-index-pagelist-container')
:addClass('mw-collapsible')
:tag('em'):wikitext(cfg.pagelist.pages.txt):done()
:wikitext(' ')
:tag('span')
:attr('id', 'ws-index-pagelist-legend')
:wikitext(cfg.pagelist.legend.txt)
:done()
:tag('div')
:attr('id', 'ws-index-pagelist')
:addClass('index-pagelist mw-collapsible-content')
:newline()
:wikitext(args.pages and mw.text.trim(args.pages))
:newline()
if args.remarks then
outerRow:tag('td')
:attr('id', 'ws-index-remarks')
:newline()
:wikitext(frame:preprocess(args.remarks))
else
outerRow:tag('td'):attr('id', 'ws-index-remarks-empty')
end
-- Notes block
if args.notes then
html:tag('div'):attr('id', 'ws-index-notes'):wikitext(args.notes)
end
-- Tracking categories
if cfg.type_cats[args.type] then
html:wikitext(construct_cat(cfg.type_cats[args.type]))
end
if cfg.source_cats[args.source] then
html:wikitext(construct_cat(cfg.source_cats[args.source]))
elseif args.source ~= 'lain-lain' then
html:wikitext(construct_cat('Indeks fail format lain'))
end
html:wikitext(construct_cat('Indeks'))
if not args.remarks then
html:wikitext(construct_cat('Laman berindeks'))
end
return talkremarks .. styles .. tostring(html) .. sortkey
end
function p.indexTemplate(frame)
return indexTemplate(frame)
end
return p
31b556w1fymb6cqb2mvp7yhwwdaxb5t
Pengguna:Hadithfajri/Laman utama/Pengepala
2
6178
22787
17938
2026-04-14T13:10:30Z
Hadithfajri
36
22787
wikitext
text/x-wiki
<templatestyles src="Laman_utama/styles.css" />
<!----baru------>
<div class="LU-outer-wrapper">
<div class="LU-logo" >
[[File:Wikisource-logo-ms.svg|150px]]
</div>
<div class="LU-content">
<div style="flex-direction: row;display: flex; justify-content: space-around;">
<div class="LU-rumi">
<div>
<div class="LU-selamat-datang">
Selamat Datang ke <span class="LU-tulisan-wiki">Wiki</span><span class="LU-tulisan-sumber">sumber</span>
</div>
<div style="margin-top: -1em; font-variant: small-caps;">
Perpustakaan [[w:Kandungan bebas|bebas]] dalam talian yang [[Wikisumber:Apa itu Wikisumber?|boleh diselenggara oleh sesiapa sahaja]].
</div>
<div style="margin-top: -0.5em; font-variant: small-caps;">
<span class="plainlinks">[//ms.m.wikisource.org Versi mudah alih] − [https://ms.wikisource.org/wiki/Laman_Utama Capaian selamat]</span>
</div>
</div>
</div>
<div class="LU-kanan-jawi">
<div class="LU-jawi" >
سلامة داتڠ <span class="LU-tulisan-jawi-wiki">کويکي</span><span class="LU-tulisan-jawi-sumber">سومبر</span>
</div>
<div style="margin-top: -1em; font-variant: small-caps;">
kini, terdapat '''[[{{ns:special}}:Statistik|{{NUMBEROFARTICLES}}]]''' koleksi teks bebas di [[w:Wikisumber|Wikisumber]].
</div>
<div style="margin-top: -0.5em; font-variant: small-caps;">
{{CURRENTDAYNAME}}, {{CURRENTDAY}} {{CURRENTMONTHNAME}} {{CURRENTYEAR}}, {{CURRENTTIME}} ([[:w:UTC|UTC]])
</div>
</div>
</div>
<!-- Bottom Navigation -->
<div class="LU-bottom-nav">
[[Wikisumber:Indeks|<span style="color:#0645AD">Indeks</span>]] '''·'''
[[Wikisumber:Gerbang komuniti|<span style="color:#0645AD">Gerbang Komuniti</span>]] '''·'''
[[Wikisumber:Kedai Kopi/Pengumuman|<span style="color:#0645AD">Pengumuman</span>]] '''·'''
[[Wikisumber:Kotak Pasir|<span style="color:#0645AD">Kotak Pasir</span>]] '''·'''
<span class="plainlinks">[http://wikimediafoundation.org/wiki/DonateNonJS/en <span style="color:#0645AD">derma</span>]</span><br>
[[:Kategori:Kategori|<span style="color:#0645AD">Kategori</span>]] ''':'''
[[:Kategori:Karya|<span style="color:#0645AD">Karya</span>]] '''·'''
[[:Kategori:Pengarang|<span style="color:#0645AD">Pengarang</span>]] '''·'''
[[:Kategori:Sumber|<span style="color:#0645AD">Sumber</span>]]
</div>
</div>
</div><p style="clear: both;"></p>
<noinclude>
[[Kategori:Laman Utama|Laman Utama]]
</noinclude>
g1t3caxyra6e3t1nh5gm51szlh7xast
Indeks:Sjaïr Kén Tamboehan, een oorspronkelijk maleisch Gedicht, met aanteekeningen uitgegeven door J.J. de Hollander; Kén Tamboehan, 1856.pdf
252
6406
22830
22687
2026-04-15T05:09:55Z
Hakimi97
9
22830
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=Sjaïr Kén Tamboehan
|Language=ms
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=9
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
hfhn6mmaysrres7gvpj1bj8z0vncuno
Indeks:Mawlid al-Nabi Or. 3289.pdf
252
7446
22781
22642
2026-04-14T12:33:56Z
Hakimi97
9
22781
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=Mawlid al-Nabi
|Language=ms-arab
|Volume=
|Author=
|Translator=
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=2
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist />
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
lkpv3ocbx4rps1n03kq6e4xb0p5km66
Indeks:Het Nieuwe Testament in het Maleisch.pdf
252
7805
22782
21783
2026-04-14T12:34:47Z
Hakimi97
9
22782
proofread-index
text/x-wiki
{{:MediaWiki:Proofreadpage_index_template
|Type=book
|wikidata_item=
|Title=Perjanjian Baru
|Language=ms-arab
|Volume=
|Author=
|Translator=Klinkert
|Editor=
|Illustrator=
|School=
|Publisher=
|Address=
|Year=
|Key=
|ISBN=
|OCLC=
|LCCN=
|BNF_ARK=
|ARC=
|DOI=
|Source=pdf
|Image=1
|Progress=X
|Transclusion=no
|Validation_date=
|Pages=<pagelist
1="Cover"
2to4="–"
5="Cover"
6="–"
7="Title"
8=4
688to692="–"
/>
|Volumes=
|Remarks=
|Width=
|Header=
|Footer=
|tmplver=
}}
s08tv5q86ov5hj3g3fh67l30lwv0v6d
Modul:Index template/config
828
7955
22824
22765
2026-04-15T04:33:46Z
Hakimi97
9
Merge Modul:Index template/indicators into Modul:Index template/config
22824
Scribunto
text/plain
local function any_case(str)
return str:gsub('.', function(chr)
if chr:match('%a') then
return '[' .. chr:lower() .. chr:upper() .. ']'
else
return chr
end
end)
end
local validation_cats = {
['dated'] = function(vdate)
return 'Indeks disahkan pada ' .. vdate
end,
['undated'] = 'Indeks disahkan tanpa tarikh',
}
return {
['param_map'] = {
['Type'] = 'type',
['Title'] = 'title',
['Subtitle'] = 'subtitle',
['Language'] = 'language',
['Volume'] = 'volume',
['Edition'] = 'edition',
['Author'] = 'author',
['Translator'] = 'translator',
['Editor'] = 'editor',
['Illustrator'] = 'illustrator',
['Publisher'] = 'publisher',
['Address'] = 'address',
['Printer'] = 'printer',
['Year'] = 'year',
['Source'] = 'source',
['Image'] = 'image',
['Progress'] = 'progress',
['Transclusion'] = 'transclusion',
['Validation_date'] = 'validation_date',
['ISBN'] = 'isbn',
['OCLC'] = 'oclc',
['LCCN'] = 'lccn',
['ARK'] = 'ark',
['DOI'] = 'doi',
['Volumes'] = 'volumes',
['Notes'] = 'notes',
['Pages'] = 'pages',
['Remarks'] = 'remarks',
['wikidata_item'] = 'wikidata_item',
},
['headings'] = {
['title'] = { ['txt'] = 'Tajuk' },
['subtitle'] = { ['txt'] = 'Subtajuk' },
['language'] = { ['txt'] = 'Bahasa' },
['volume'] = { ['txt'] = 'Jilid' },
['edition'] = { ['txt'] = 'Edisi' },
['author'] = { ['txt'] = 'Pengarang' },
['translator'] = { ['txt'] = 'Penterjemah' },
['editor'] = { ['txt'] = 'Penyunting' },
['illustrator'] = { ['txt'] = 'Pengilustrasi' },
['publisher'] = { ['txt'] = 'Penerbit' },
['address'] = { ['txt'] = 'Alamat' },
['publishedin'] = { ['txt'] = 'Alamat penerbitan' },
['year'] = { ['txt'] = 'Tahun' },
['inception'] = { ['txt'] = 'Tarikh terawal' },
['printer'] = { ['txt'] = 'Pencetak' },
['source'] = { ['txt'] = 'Sumber' },
['progress'] = { ['txt'] = 'Kemajuan' },
['transclusion'] = { ['txt'] = 'Transklusi' },
['validation_date'] = { ['txt'] = 'Tarikh pengesahan' },
['isbn'] = { ['txt'] = 'ISBN' },
['oclc'] = { ['txt'] = 'OCLC' },
['lccn'] = { ['txt'] = 'LCCN' },
['ark'] = { ['txt'] = 'ARK' },
['doi'] = { ['txt'] = 'DOI' },
['volumes'] = { ['txt'] = 'Siri' },
},
['status'] = {
['T'] = {
['cat'] = 'Indeks disahkan',
['txt'] = 'Selesai disahkan',
},
['V'] = {
['cat'] = 'Indeks telah dibacaprufkan',
['txt'] = 'Akan disahkan',
},
['C'] = {
['cat'] = 'Indeks belum dibacaprufkan',
['txt'] = 'Akan dibacaprufkan',
},
['OCR'] = {
['cat'] = 'Indeks - Lapisan Teks Diperlukan',
['txt'] = 'Perlu tambah lapisan teks OCR',
},
['L'] = {
['cat'] = 'Indeks - Fail yang perlu dibaiki',
['txt'] = 'Fail sumber cacat',
['error'] = true,
},
['X'] = {
['cat'] = 'Indeks - Fail untuk disemak',
['txt'] = 'Semak kesemua muka surat pada fail sumber sebelum memulakan proses baca pruf (untuk mengesahkan fail tersebut tidak ada masalah)',
['error'] = true,
},
['_missing'] = {
['cat'] = 'Indeks - Kemajuan tidak diketahui',
['txt'] = 'Kemajuan tidak diketahui (ralat templat)',
['error'] = true,
},
['_default'] = {
['cat'] = 'Indeks - Kemajuan tidak diketahui',
['txt'] = function(index_status)
return 'Kemajuan tidak diketahui: ' .. index_status .. ' (ralat templat)'
end,
['error'] = true,
}
},
['transclusion'] = {
['yes'] = {
['cat'] = 'Ditransklusi sepenuhnya',
['txt'] = 'Ditransklusi sepenuhnya',
},
['notimg'] = {
['cat'] = 'Imej belum ditransklusi sepenuhnya',
['txt'] = 'Imej belum ditransklusi sepenuhnya',
},
['notadv'] = {
['cat'] = 'Bahan pengiklanan belum ditransklusi',
['txt'] = 'Bahan pengiklanan belum ditransklusi',
},
['held'] = {
['cat'] = 'Transklusi ditangguhkan',
['txt'] = 'Transklusi ditangguhkan',
},
['check'] = {
['cat'] = 'Semakan transklusi diperlukan',
['txt'] = 'Semakan transklusi diperlukan',
},
['no'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = 'Indeks belum ditransklusi mahupun diperiksa',
},
['_missing'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = 'Status transklusi tiada (ralat templat)',
['error'] = true,
},
['_default'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = function(index_status)
return 'Status transklusi tidak diketahui: ' .. index_status .. ' (ralat templat)'
end,
['error'] = true,
}
},
['validation_cats'] = validation_cats,
['url_gens'] = {
['isbn'] = function(id, text)
return require('Module:ISBN')._ISBN({id})
end,
['oclc'] = function(id, text)
return '[https://www.worldcat.org/oclc/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
['lccn'] = function(id, text)
return '[https://lccn.loc.gov/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
['ark'] = function(id, text)
return '[https://n2t.net/' .. mw.uri.encode(id, 'QUERY') .. ' ' .. text .. ']'
end,
['doi'] = function(id, text)
return '[https://doi.org/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
},
['cover'] = {
['width'] = '250px',
['image'] = 'File:Placeholder book.svg'
},
['cover_cats'] = {
['file_types'] = {
['jpg'] = 'image',
['png'] = 'image',
['gif'] = 'image',
['tif'] = 'image',
['ogg'] = 'audiovisual',
['ogv'] = 'audiovisual',
['webm'] = 'audiovisual',
['pdf'] = 'multipage',
['djvu'] = 'multipage',
['_empty_'] = 'unknown',
},
['image'] = 'Indeks fail imej',
['audiovisual'] = 'Indeks fail audiovizual',
['unknown'] = 'Indeks jenis tidak diketahui',
['missing'] = 'Indeks dengan fail hilang',
['fullspec'] = 'Indeks bukan imej dengan imej kulit ditentukan sepenuhnya',
},
['type_cats'] = {
['book'] = 'Indeks - Buku',
['journal'] = 'Indeks - Jurnal',
['collection'] = 'Indeks - Koleksi',
['dictionary'] = 'Indeks - Kamus',
['phdthesis'] = 'Indeks - Tesis',
},
['source_cats'] = {
['djvu'] = 'Indeks fail DjVu',
['pdf'] = 'Indeks fail PDF',
['jpg'] = 'Indeks fail JPG',
['png'] = 'Indeks fail PNG',
['gif'] = 'Indeks fail GIF',
['tif'] = 'Indeks fail TIF',
['ogg'] = 'Indeks fail OGG',
['ogv'] = 'Indeks fail OGV',
['webm'] = 'Indeks fail WebM',
},
['pagelist'] = {
['pages'] = { ['txt'] = 'Senarai muka surat' },
['legend'] = { ['txt'] = '(kunci kepada [[Bantuan:Status_laman|Status Laman]])' }
},
['missing_heading_id'] = function(id)
return 'Tidak jumpa tajuk untuk ID: ' .. id
end,
['indicator_defaults'] = {
['width'] = '20px',
['include'] = function(args) return true end,
},
['indicators'] = {
{
name = 'pagegame',
image = 'File:OOjs UI icon page number.svg',
width = '20px',
link = function(args)
return tostring(mw.uri.fullUrl('toolforge:ws-page-game', {
wikisource = 'ms',
index = mw.uri.encode(args.fileTitle.rootText),
lang = 'ms',
}))
end,
caption = 'Permainan Laman Wikisumber (pembina senarai muka surat langkah-demi-langkah)',
},
{
name = 'purge file',
image = 'File:OOjs UI icon reload.svg',
width = '20px',
link = function(args)
return tostring(mw.uri.fullUrl(
'Indeks:' .. args.pageTitle.text, { action = 'purge' }
))
end,
caption = 'Bersihkan fail',
},
{
name = 'book2scroll',
image = 'File:Library-logo-blue-outline.png',
width = '18px',
link = function(args)
return tostring(mw.uri.fullUrl(
'toolforge:book2scrollv2/read/ms/' ..
mw.uri.encode(args.fileTitle.rootText)
))
end,
caption = 'Buka pada Book2Scroll',
},
{
name = 'bookreader',
image = 'File:BookReader-favicon.svg',
width = '18px',
link = function(args)
return tostring(mw.uri.fullUrl(
'toolforge:bookreader/ms/' ..
mw.uri.encode(args.fileTitle.rootText)
))
end,
caption = 'Buka fail pada BookReader',
},
{
name = 'validated-index-date',
image = 'File:Yes Check Circle.svg',
width = '15px',
alt = 'Laman indeks yang disahkan.',
link = function(args)
local vdate = args.validation_date
return vdate
and tostring(mw.uri.fullUrl(
'Kategori:' .. validation_cats.dated(vdate)
))
or ''
end,
caption = function(args)
local vdate = args.validation_date
return vdate and 'Disahkan pada ' .. vdate or nil
end,
include = function(args)
return args.validation_date ~= nil
end,
},
},
['talkremarks'] = {
['text'] = function(args)
return 'Garis panduan pemformatan khusus untuk karya ini mungkin telah ditetapkan. Sila semak [[' .. args.talkPageTitle.prefixedText .. '|laman perbincangan Indeks ini]] dan patuhi sebarang kelaziman yang berkaitan.'
end,
['cat'] = 'Laman yang menggunakan catatan perbincangan indeks dengan parameter nota',
['keywords'] = {
-- Kata kunci Melayu
{
['pattern'] = any_case('nota?'),
['alone'] = true,
},
{
['pattern'] = any_case('nota? ringkas'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? bacapruf'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? gaya'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? tataletak'),
['alone'] = false,
},
{
['pattern'] = any_case('konvensyen? pemformatan'),
['alone'] = false,
},
{
['pattern'] = any_case('pemformatan'),
['alone'] = true,
},
{
['pattern'] = any_case('konvensyen?'),
['alone'] = true,
},
{
['pattern'] = any_case('tataletak'),
['alone'] = true,
},
{
['pattern'] = any_case('petikan'),
['alone'] = true,
},
{
['pattern'] = any_case('tanda petikan'),
['alone'] = false,
},
{
['pattern'] = any_case('tipografi'),
['alone'] = false,
},
{
['pattern'] = any_case('ejaan'),
['alone'] = false,
},
{
['pattern'] = any_case('panduan gaya'),
['alone'] = false,
},
{
['pattern'] = any_case('garis? panduan?'),
['alone'] = false,
},
{
['pattern'] = any_case('laman? hilang'),
['alone'] = true,
},
-- Kata kunci Inggeris (untuk keserasian)
{
['pattern'] = any_case('notes?'),
['alone'] = true,
},
{
['pattern'] = any_case('formatting conventions?'),
['alone'] = false,
},
{
['pattern'] = any_case('formatt?i?n?g?'),
['alone'] = true,
},
{
['pattern'] = any_case('conventions?'),
['alone'] = true,
},
{
['pattern'] = any_case('guidelines?'),
['alone'] = false,
},
{
['pattern'] = any_case('style guide'),
['alone'] = false,
},
{
['pattern'] = any_case('spelling'),
['alone'] = false,
},
{
['pattern'] = any_case('typography'),
['alone'] = false,
},
{
['pattern'] = any_case('long[ %-]s'),
['alone'] = true,
},
},
},
}
ib7jttigz6fv1p8ke949w6y70jcrl6r
22827
22824
2026-04-15T05:08:50Z
Hakimi97
9
Code consolidation
22827
Scribunto
text/plain
local function any_case(str)
return str:gsub('.', function(chr)
if chr:match('%a') then
return '[' .. chr:lower() .. chr:upper() .. ']'
else
return chr
end
end)
end
-- Inverted param_map: maps lua-key → Title-Case wikitext key.
-- Used by Modul:Arguments in the data module to resolve template parameters.
local param_map = {
['Type'] = 'type',
['Title'] = 'title',
['Subtitle'] = 'subtitle',
['Language'] = 'language',
['Volume'] = 'volume',
['Edition'] = 'edition',
['Author'] = 'author',
['Translator'] = 'translator',
['Editor'] = 'editor',
['Illustrator'] = 'illustrator',
['Publisher'] = 'publisher',
['Address'] = 'address',
['Printer'] = 'printer',
['Year'] = 'year',
['Source'] = 'source',
['Image'] = 'image',
['Progress'] = 'progress',
['Transclusion'] = 'transclusion',
['Validation_date'] = 'validation_date',
['ISBN'] = 'isbn',
['OCLC'] = 'oclc',
['LCCN'] = 'lccn',
['ARK'] = 'ark',
['DOI'] = 'doi',
['Volumes'] = 'volumes',
['Notes'] = 'notes',
['Pages'] = 'pages',
['Remarks'] = 'remarks',
['wikidata_item'] = 'wikidata_item',
}
local translate = {}
for titleCase, lowerCase in pairs(param_map) do
translate[lowerCase] = titleCase
end
local validation_cats = {
['dated'] = function(vdate)
return 'Indeks disahkan pada ' .. vdate
end,
['undated'] = 'Indeks disahkan tanpa tarikh',
}
return {
['param_map'] = param_map,
['translate'] = translate,
['headings'] = {
['title'] = { ['txt'] = 'Tajuk' },
['subtitle'] = { ['txt'] = 'Subtajuk' },
['language'] = { ['txt'] = 'Bahasa' },
['volume'] = { ['txt'] = 'Jilid' },
['edition'] = { ['txt'] = 'Edisi' },
['author'] = { ['txt'] = 'Pengarang' },
['translator'] = { ['txt'] = 'Penterjemah' },
['editor'] = { ['txt'] = 'Penyunting' },
['illustrator'] = { ['txt'] = 'Pengilustrasi' },
['publisher'] = { ['txt'] = 'Penerbit' },
['address'] = { ['txt'] = 'Alamat' },
['publishedin'] = { ['txt'] = 'Alamat penerbitan' },
['year'] = { ['txt'] = 'Tahun' },
['inception'] = { ['txt'] = 'Tarikh terawal' },
['printer'] = { ['txt'] = 'Pencetak' },
['source'] = { ['txt'] = 'Sumber' },
['progress'] = { ['txt'] = 'Kemajuan' },
['transclusion'] = { ['txt'] = 'Transklusi' },
['validation_date'] = { ['txt'] = 'Tarikh pengesahan' },
['isbn'] = { ['txt'] = 'ISBN' },
['oclc'] = { ['txt'] = 'OCLC' },
['lccn'] = { ['txt'] = 'LCCN' },
['ark'] = { ['txt'] = 'ARK' },
['doi'] = { ['txt'] = 'DOI' },
['volumes'] = { ['txt'] = 'Siri' },
},
['status'] = {
['T'] = {
['cat'] = 'Indeks disahkan',
['txt'] = 'Selesai disahkan',
},
['V'] = {
['cat'] = 'Indeks telah dibacaprufkan',
['txt'] = 'Akan disahkan',
},
['C'] = {
['cat'] = 'Indeks belum dibacaprufkan',
['txt'] = 'Akan dibacaprufkan',
},
['OCR'] = {
['cat'] = 'Indeks - Lapisan Teks Diperlukan',
['txt'] = 'Perlu tambah lapisan teks OCR',
},
['L'] = {
['cat'] = 'Indeks - Fail yang perlu dibaiki',
['txt'] = 'Fail sumber cacat',
['error'] = true,
},
['X'] = {
['cat'] = 'Indeks - Fail untuk disemak',
['txt'] = 'Semak kesemua muka surat pada fail sumber sebelum memulakan proses baca pruf (untuk mengesahkan fail tersebut tidak ada masalah)',
['error'] = true,
},
['_missing'] = {
['cat'] = 'Indeks - Kemajuan tidak diketahui',
['txt'] = 'Kemajuan tidak diketahui (ralat templat)',
['error'] = true,
},
['_default'] = {
['cat'] = 'Indeks - Kemajuan tidak diketahui',
['txt'] = function(index_status)
return 'Kemajuan tidak diketahui: ' .. index_status .. ' (ralat templat)'
end,
['error'] = true,
}
},
['transclusion'] = {
['yes'] = {
['cat'] = 'Ditransklusi sepenuhnya',
['txt'] = 'Ditransklusi sepenuhnya',
},
['notimg'] = {
['cat'] = 'Imej belum ditransklusi sepenuhnya',
['txt'] = 'Imej belum ditransklusi sepenuhnya',
},
['notadv'] = {
['cat'] = 'Bahan pengiklanan belum ditransklusi',
['txt'] = 'Bahan pengiklanan belum ditransklusi',
},
['held'] = {
['cat'] = 'Transklusi ditangguhkan',
['txt'] = 'Transklusi ditangguhkan',
},
['check'] = {
['cat'] = 'Semakan transklusi diperlukan',
['txt'] = 'Semakan transklusi diperlukan',
},
['no'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = 'Indeks belum ditransklusi mahupun diperiksa',
},
['_missing'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = 'Status transklusi tiada (ralat templat)',
['error'] = true,
},
['_default'] = {
['cat'] = 'Indeks belum ditransklusi',
['txt'] = function(index_status)
return 'Status transklusi tidak diketahui: ' .. index_status .. ' (ralat templat)'
end,
['error'] = true,
}
},
['validation_cats'] = validation_cats,
['url_gens'] = {
['isbn'] = function(id, text)
return require('Module:ISBN')._ISBN({id})
end,
['oclc'] = function(id, text)
return '[https://www.worldcat.org/oclc/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
['lccn'] = function(id, text)
return '[https://lccn.loc.gov/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
['ark'] = function(id, text)
return '[https://n2t.net/' .. mw.uri.encode(id, 'QUERY') .. ' ' .. text .. ']'
end,
['doi'] = function(id, text)
return '[https://doi.org/' .. mw.uri.encode(id, 'PATH') .. ' ' .. text .. ']'
end,
},
['cover'] = {
['width'] = '250px',
['image'] = 'File:Placeholder book.svg'
},
['cover_cats'] = {
['file_types'] = {
['jpg'] = 'image',
['png'] = 'image',
['gif'] = 'image',
['tif'] = 'image',
['ogg'] = 'audiovisual',
['ogv'] = 'audiovisual',
['webm'] = 'audiovisual',
['pdf'] = 'multipage',
['djvu'] = 'multipage',
['_empty_'] = 'unknown',
},
['image'] = 'Indeks fail imej',
['audiovisual'] = 'Indeks fail audiovizual',
['unknown'] = 'Indeks jenis tidak diketahui',
['missing'] = 'Indeks dengan fail hilang',
['fullspec'] = 'Indeks bukan imej dengan imej kulit ditentukan sepenuhnya',
},
['type_cats'] = {
['book'] = 'Indeks - Buku',
['journal'] = 'Indeks - Jurnal',
['collection'] = 'Indeks - Koleksi',
['dictionary'] = 'Indeks - Kamus',
['phdthesis'] = 'Indeks - Tesis',
},
['linkable_sources'] = {
djvu=true, pdf=true, png=true, gif=true,
tif=true, ogg=true, ogv=true, webm=true,
},
['source_cats'] = {
['djvu'] = 'Indeks fail DjVu',
['pdf'] = 'Indeks fail PDF',
['jpg'] = 'Indeks fail JPG',
['png'] = 'Indeks fail PNG',
['gif'] = 'Indeks fail GIF',
['tif'] = 'Indeks fail TIF',
['ogg'] = 'Indeks fail OGG',
['ogv'] = 'Indeks fail OGV',
['webm'] = 'Indeks fail WebM',
},
['pagelist'] = {
['pages'] = { ['txt'] = 'Senarai muka surat' },
['legend'] = { ['txt'] = '(kunci kepada [[Bantuan:Status_laman|Status Laman]])' }
},
['missing_heading_id'] = function(id)
return 'Tidak jumpa tajuk untuk ID: ' .. id
end,
['indicator_defaults'] = {
['width'] = '20px',
['include'] = function(args) return true end,
},
['indicators'] = {
{
name = 'pagegame',
image = 'File:OOjs UI icon page number.svg',
width = '20px',
link = function(args)
return tostring(mw.uri.fullUrl('toolforge:ws-page-game', {
wikisource = 'ms',
index = mw.uri.encode(args.fileTitle.rootText),
lang = 'ms',
}))
end,
caption = 'Permainan Laman Wikisumber (pembina senarai muka surat langkah-demi-langkah)',
},
{
name = 'purge file',
image = 'File:OOjs UI icon reload.svg',
width = '20px',
link = function(args)
return tostring(mw.uri.fullUrl(
'Indeks:' .. args.pageTitle.text, { action = 'purge' }
))
end,
caption = 'Bersihkan fail',
},
{
name = 'book2scroll',
image = 'File:Library-logo-blue-outline.png',
width = '18px',
link = function(args)
return tostring(mw.uri.fullUrl(
'toolforge:book2scrollv2/read/ms/' ..
mw.uri.encode(args.fileTitle.rootText)
))
end,
caption = 'Buka pada Book2Scroll',
},
{
name = 'bookreader',
image = 'File:BookReader-favicon.svg',
width = '18px',
link = function(args)
return tostring(mw.uri.fullUrl(
'toolforge:bookreader/ms/' ..
mw.uri.encode(args.fileTitle.rootText)
))
end,
caption = 'Buka fail pada BookReader',
},
{
name = 'validated-index-date',
image = 'File:Yes Check Circle.svg',
width = '15px',
alt = 'Laman indeks yang disahkan.',
link = function(args)
local vdate = args.validation_date
return vdate
and tostring(mw.uri.fullUrl(
'Kategori:' .. validation_cats.dated(vdate)
))
or ''
end,
caption = function(args)
local vdate = args.validation_date
return vdate and 'Disahkan pada ' .. vdate or nil
end,
include = function(args)
return args.validation_date ~= nil
end,
},
},
['talkremarks'] = {
['text'] = function(args)
return 'Garis panduan pemformatan khusus untuk karya ini mungkin telah ditetapkan. Sila semak [[' .. args.talkPageTitle.prefixedText .. '|laman perbincangan Indeks ini]] dan patuhi sebarang kelaziman yang berkaitan.'
end,
['cat'] = 'Laman yang menggunakan catatan perbincangan indeks dengan parameter nota',
['keywords'] = {
-- Kata kunci Melayu
{
['pattern'] = any_case('nota?'),
['alone'] = true,
},
{
['pattern'] = any_case('nota? ringkas'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? bacapruf'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? gaya'),
['alone'] = false,
},
{
['pattern'] = any_case('nota? tataletak'),
['alone'] = false,
},
{
['pattern'] = any_case('konvensyen? pemformatan'),
['alone'] = false,
},
{
['pattern'] = any_case('pemformatan'),
['alone'] = true,
},
{
['pattern'] = any_case('konvensyen?'),
['alone'] = true,
},
{
['pattern'] = any_case('tataletak'),
['alone'] = true,
},
{
['pattern'] = any_case('petikan'),
['alone'] = true,
},
{
['pattern'] = any_case('tanda petikan'),
['alone'] = false,
},
{
['pattern'] = any_case('tipografi'),
['alone'] = false,
},
{
['pattern'] = any_case('ejaan'),
['alone'] = false,
},
{
['pattern'] = any_case('panduan gaya'),
['alone'] = false,
},
{
['pattern'] = any_case('garis? panduan?'),
['alone'] = false,
},
{
['pattern'] = any_case('laman? hilang'),
['alone'] = true,
},
-- Kata kunci Inggeris (untuk keserasian)
{
['pattern'] = any_case('notes?'),
['alone'] = true,
},
{
['pattern'] = any_case('formatting conventions?'),
['alone'] = false,
},
{
['pattern'] = any_case('formatt?i?n?g?'),
['alone'] = true,
},
{
['pattern'] = any_case('conventions?'),
['alone'] = true,
},
{
['pattern'] = any_case('guidelines?'),
['alone'] = false,
},
{
['pattern'] = any_case('style guide'),
['alone'] = false,
},
{
['pattern'] = any_case('spelling'),
['alone'] = false,
},
{
['pattern'] = any_case('typography'),
['alone'] = false,
},
{
['pattern'] = any_case('long[ %-]s'),
['alone'] = true,
},
},
},
}
clrzkn7oi5jojq8kwry66y2lrfddi0p
Modul:Index template/doc
828
7960
22792
22773
2026-04-14T13:26:03Z
Hakimi97
9
Document the module
22792
wikitext
text/x-wiki
{{lua|Modul:Arguments|Modul:ISO 639|Modul:Category handler|Modul:File link|Modul:Message box|Modul:Index template/config|Modul:Index template/indicators|Modul:Index template/data|Modul:Index template/styles.css|Templat:Author link|Templat:Index talk remarks}}
This is the current module to implement logic for [[MediaWiki:Proofreadpage index template]], based on [[:mediawikiwiki:Wikidata - Wikisource Integration Modules|Wikidata - Wikisource Integration Modules]] on MediaWiki with significant changes:
# Reconfiguration of index page panel structure (which includes image, metadata, pagelist, and remarks/notes sections) to follow the structure on [[:en:Module:Proofreadpage index template|Module:Proofreadpage index template]].
# Adaptation new metadata fields from [[:en:Module:Proofreadpage index template|Module:Proofreadpage index template]]: (1) language parameter and categorization, ensuring manually-entered language code would return language canonical names; (2) transclusion status; (3) validation date; (4) ISBN/OCLC/LCCN/ARK/DOI; (5) talk page remark related functionality; (6) missing file tracking category; (7) full image spec tracking category; and (8) audiovisual thumbtime cover
# Sufficient gap between image and metadata
# Sufficient gap between labels and values of metadata
# Author property value changed to P50 instead of P253075
# Ensured all file types under the source parameter could be wikilinked.
# The wikilinks for title, author, translator and editor fields could be generated automatically or manually
# Simplified the invocation of the module at MediaWiki:Proofreadpage index template so that no explicit mentioning of parameters and indicators.
# Integration of Modul:Index data into Modul:Index template, with the new name Modul:Index template/data.
# Replaced the usage of transclusion_checker indicator (external toolforge link) to [[MediaWiki:Gadget-transclusion-check|transclusion check gadget]].
# Utilized the [[Modul:Arguments]] for getArgs.
<noinclude>[[Category:External links on protected pages]]</noinclude>
45utd2wedyfcgvpfa1rrj7j5xhe3sxw
22826
22792
2026-04-15T04:35:27Z
Hakimi97
9
22826
wikitext
text/x-wiki
{{lua|Modul:Arguments|Modul:ISO 639|Modul:Category handler|Modul:File link|Modul:Message box|Modul:Index template/config|Modul:Index template/data|Modul:Index template/styles.css|Templat:Author link|Templat:Index talk remarks}}
This is the current module to implement logic for [[MediaWiki:Proofreadpage index template]], based on [[:mediawikiwiki:Wikidata - Wikisource Integration Modules|Wikidata - Wikisource Integration Modules]] on MediaWiki with significant changes:
# Reconfiguration of index page panel structure (which includes image, metadata, pagelist, and remarks/notes sections) to follow the structure on [[:en:Module:Proofreadpage index template|Module:Proofreadpage index template]].
# Adaptation new metadata fields from [[:en:Module:Proofreadpage index template|Module:Proofreadpage index template]]: (1) language parameter and categorization, ensuring manually-entered language code would return language canonical names; (2) transclusion status; (3) validation date; (4) ISBN/OCLC/LCCN/ARK/DOI; (5) talk page remark related functionality; (6) missing file tracking category; (7) full image spec tracking category; and (8) audiovisual thumbtime cover
# Sufficient gap between image and metadata
# Sufficient gap between labels and values of metadata
# Author property value changed to P50 instead of P253075
# Ensured all file types under the source parameter could be wikilinked.
# The wikilinks for title, author, translator and editor fields could be generated automatically or manually
# Simplified the invocation of the module at MediaWiki:Proofreadpage index template so that no explicit mentioning of parameters and indicators.
# Integration of Modul:Index data into Modul:Index template, with the new name Modul:Index template/data.
# Replaced the usage of transclusion_checker indicator (external toolforge link) to [[MediaWiki:Gadget-transclusion-check|transclusion check gadget]].
# Utilized the [[Modul:Arguments]] for getArgs.
<noinclude>[[Category:External links on protected pages]]</noinclude>
725x2nyyru4kyhtv7eysz1isgkoanvf
Laman:Syair Lampung Karam.pdf/19
250
7962
22793
2026-04-14T13:33:39Z
Hadithfajri
36
/* Belum dibaca pruf */ Mencipta laman baru dengan kandungan '{{رڠکڤ|سده دفريقسا کونن سموا \\ دسوره تڠکل فول دتمفتڽ منا يڠ سوک دتڠکوڽ \\ ادا يڠ ستڠه منجادي صحابتڽ سفأروه برکات کفد سکلين \\ دودق دتمفة کيت دکسيه ماکن بيسؤله هاري دفريقساکن \\ فرسيدين داتڠ دوا سکاوان ستڠه اوراڠ منتأ فرميسي \\ فرکي کفد صحبة دان هندي بيسؤ ها...'
22793
proofread-page
text/x-wiki
<noinclude><pagequality level="1" user="Hadithfajri" /></noinclude>{{رڠکڤ|سده دفريقسا کونن سموا \\ دسوره تڠکل فول دتمفتڽ
منا يڠ سوک دتڠکوڽ \\ ادا يڠ ستڠه منجادي صحابتڽ
سفأروه برکات کفد سکلين \\ دودق دتمفة کيت دکسيه ماکن
بيسؤله هاري دفريقساکن \\ فرسيدين داتڠ دوا سکاوان
ستڠه اوراڠ منتأ فرميسي \\ فرکي کفد صحبة دان هندي
بيسؤ هاري داتڠ کسيني \\ منڠکو فرنته دباوه دولي
فاکي هاري ڽتله توان \\ اداله کيرا٢ دوکل دلافن
داتڠ برکومفول برکاوان٢ \\ مندافتکن سکاوة اي سکلين
فوکل سمبيلن ڽتاله تنتو \\ داتڠ سقاوة ملهتکن ايت}}<noinclude></noinclude>
c92mz85otgf13oq3k8pmmqvzbwim9xv
Laman:Pelita Brunei-1 Januari 1959.pdf/7
250
7963
22795
2026-04-14T14:17:10Z
Rombituon
510
/* Belum dibaca pruf */ Mencipta laman baru dengan kandungan 'RANCHANGAN PERHIASAN KUALA BLAIT-SERIA. JAWATAN Kuasa Lawatan Diraja, Kuala Belait telah menerima lukisan2 dan chadangan yang di-sampaikan oleh Tuan ".B.H.Rackham kerana per- hiasan sa-panjang jalan yang akan di-lalui oleh Yang Amat Mulia Duke of Edinburgh apabila beliau melawat ka-Kuala Belait dan Seria hari Sabtu 28 February yang akan datang ini. {{inden teks|2em|Pada am-nya perhiasan2 itu akan berasaskan pada ka-Dirajaan.}} {...
22795
proofread-page
text/x-wiki
<noinclude><pagequality level="1" user="Rombituon" /></noinclude>RANCHANGAN PERHIASAN KUALA BLAIT-SERIA.
JAWATAN Kuasa Lawatan Diraja, Kuala Belait telah menerima lukisan2
dan chadangan yang di-sampaikan oleh Tuan ".B.H.Rackham kerana per-
hiasan sa-panjang jalan yang akan di-lalui oleh Yang Amat Mulia
Duke of Edinburgh apabila beliau melawat ka-Kuala Belait dan Seria
hari Sabtu 28 February yang akan datang ini.
{{inden teks|2em|Pada am-nya perhiasan2 itu akan berasaskan pada ka-Dirajaan.}}
{{inden teks|2em|Sa-keping panji2 besar dengan ayat "Selamat Datang ka-Daerah
Kuala Belait, Negeri Brunei" akan di-kibarkan di-lapangan terbang
Anduki tempat Duke of Edinburgh turun ke-bumi Negeri Brunei pada
pagi hari itu dari Sarawak. Sa-lepas itu beliau akan menaiki kende-
raan melalui Jalan Tengah ka-Seria.}}
{{inden teks|2em|Dalam perjalanan itu perarakan motokar2 akan melalui sa-buah
pintu gerbang yang akan di-bena di-simpang Jalan Tengah dengan
Lorong Tengah.}}
{{inden teks|2em|Di-padang Marina, Duke of Edinburgh akan meme eksa perbarisan
yang terdiri dari murid2 sekolah tempatan, pengakap dan lain2 per-
tubohan kaum. Beberapa lukisan menggambarkan kebesaran Diraja akan
di-pertunjokkan di-padang itu.}}
{{inden teks|2em|Sa-masa memereksa perbarisan itu Duke of "inburgh akan berjalan
i-bawah empat buah pintu gerbang yang akan di-bena oleh kaum
Melayu, China, Indian dan Dayak dan Dusun di-aerah Kuala Belait.}}
{{inden teks|2em|Dalam perjalanan-nya ka-Penaga Club kerana ha hir dalam majlis
jamuan kerajaan Duke of Edinburgh akan berjalan dekat tiga batang
tiang besi 30 kaki tinggi menjunjong sa-buah mahkota.}}
{{inden teks|2em|Jalan2 yang akan di-lalui oleh Duke di-kawasan padang minyak itu
akan di-hiasi dengan bendera 2 Negeri Brunei an negeri2 Commonwealth.}}
*******************
PERHUBONGAN TALIPON BRUNEI-LABILAN.
{{inden teks|2em|Perkhidmatan talipon V.H.F. di-antara Brunei engan Labuan akan
di-mulakan eri hari ini saperti berikut:}}
{{inden teks|2em|Hari Ahad dan hari kelepasan dari pukul 7.30 pagi hingga
pukul 12.30 tengah hari.}}
{{inden teks|2em|Lain2 hari termasok Juma'at dan Sabtu dari pukul 7.30 pagi
hingga pukul 6 petang.}}
**********************
WAYANG GAMBAR PEJABAT PENERANGAN.
{{inden teks|2em|Jadual pertunjókan wayang gambar Pejabat Penerangan, Kuala Belait
bagi bulan ini in-leh saperti di-bawah ini:}}
{{inden teks|2em|7 January, Labi; 6 Jenuery, Rampayoh; 7 January, Raten; 8 January
Bukit Punn; 12 January, Lorong 14, Polis Serie; 13 January, Penage
Field Force; 14 January, Padang Kechil, Kuala Belait; 15 January,
Rumah Orang Miskin, Seria; 16 January, Sungai Teraban, Kuala Belait;
26 January, Danau; 27 January, Telisi; 28 January Liang dan 29
January, Lumut.}}
*************************
{{inden teks|2em|Hakim Besar, Brunei, Sir Ernest Williams, telah i-perkenankan
oleh Baginda Queen Can Duli Yang Maha Mulia berhenti eri perkhid-
matan sa-telah habis chuti yang akan di-ambil-nyr pada hujong
bulan March hadapan ini.}}<noinclude></noinclude>
dg041ar6wo1mlrc7tzyp6jj41tbel8a
Laman:Pelita Brunei-1 Januari 1959.pdf/8
250
7964
22796
2026-04-14T14:20:11Z
Rombituon
510
/* Belum dibaca pruf */ Mencipta laman baru dengan kandungan 'ISTI'ADAT PEMBUKAAN ANTHONY. ABELL COLLEGE {{inden teks|2em|Yang Terutama Pesuroh Jaya Tinggi Brunei, Dato Paduka Sir Anthony Abell, telah mengistiharkan pembukaan rasmi sekolah menengah Brunei yang kedua, di-Seria pada 18 December, yang lalu.}} {{inden teks|2em|Sekolah itu di-namakan Anthony Abell College kerana meng- ambil sempena dari nama Pesuroh Jaya Tinggi itu.}} {{inden teks|2em|Sekolah itu belum siap lagi. Sa-banyak $1,5...
22796
proofread-page
text/x-wiki
<noinclude><pagequality level="1" user="Rombituon" /></noinclude>ISTI'ADAT PEMBUKAAN ANTHONY. ABELL COLLEGE
{{inden teks|2em|Yang Terutama Pesuroh Jaya Tinggi Brunei, Dato Paduka Sir
Anthony Abell, telah mengistiharkan pembukaan rasmi sekolah
menengah Brunei yang kedua, di-Seria pada 18 December, yang
lalu.}}
{{inden teks|2em|Sekolah itu di-namakan Anthony Abell College kerana meng-
ambil sempena dari nama Pesuroh Jaya Tinggi itu.}}
{{inden teks|2em|Sekolah itu belum siap lagi. Sa-banyak $1,580,000 akan di-
belanjakan dalam tahun ini kerana pembenaan peringkat pengha-
bisan.}}
{{inden teks|2em|Apabila sekolah itu siap kelak Sir Anthony berharap moga2
ia-nya akan di-akui di-seluroh Borneo sa-bagai sa-buah seko-
lah yang mengeluarkan pemimpin2 yang chekap dan berani
dan perempuan yang jauh pemandangan dan chenderong kapada sim-
pati international dalam menjalankan tugas mereka memimpin
anak2 negeri.}}
{{inden teks|2em|Dalam uchapan-nya sa-jurus sa-belum mendedahkan kain tu-
dong papan peringatan pembenaan sekolah itu Sir Anthony telah
mengingatkan bahawa satu perkara yang sangat di-perlukan oleh
Brunei pada masa ini dan di-masa hadapan ia-lah pemimpin2.}}
{{inden teks|2em|Pemimpin2 ada-lah di-kehendaki kerana Duli Yang Maha Mulia
berchi ta2 hendak memberi satu perlembagaan baharu kapada Bru-
nei supaya dapat anak2 Brunei memikul beban pemerentahan yang
lebeh berat dari yang sudah2.}}
{{inden teks|2em|Pemimpin yang baik dan sehat hanya-lah dapat di-berikan
oleh mereka yang waras fikiran-nya dan tidak memikirkan kepen-
tingan dan keuntongan diri sendiri dan mereka itu hendak-lah
berani, yakin dan mahu merintis jalan.}}
{{inden teks|2em|Sir Anthony telah menegaskan bahawa kemudahan2 pelajaran
yang di-beri oleh Negeri Brunei kapada anak2 Brunei ada-lah
lebeh maju dari lain2 negeri di-Borneo ini dan barangkali juga
dari lain2 negeri di-Tenggara Asia.}}
{{inden teks|2em|Ini memberi harapan baik kapada Brunei dan satu chabaran
besar kapada anak2 Brunei yang cherdek dan berusaha. Mahu-kah
pemuda pemudi Brunei itu mengambil peluang ini untok mensesu-
aikan diri mereka menjadi pemimpin2? Sir Anthony bertanya.}}
{{inden teks|2em|Di-antara lain2 Sir Anthony telah mengingatkan murid2 se-
kolah itu bahawa Negeri Brunei berkehendakkan ramai pegawai2
pertanian, ahli2 sains, pegawai2 hutan, doktor2, jurutera2
dan lain2 pegawai yang berkelulusan.}}
{{inden teks|2em|"Saya perchaya satu perkara yang penting dalam didekan pelaja-
ran ia-lah sa-saorang itu hendak-lah bersedia melateh diri-nya}}
- bersambong di-muke -<noinclude></noinclude>
tjix05v63j4j3f0pb5v4nndtf05wd3i
Templat:Atribut HTML
10
7965
22798
2026-04-14T15:42:18Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Atribut HTML]] ke [[Templat:HTML attribute]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22798
wikitext
text/x-wiki
#LENCONG [[Templat:HTML attribute]]
iwrb5lfmwc3esw6j9s1w4juvg6qwvgh
Modul:Atribut HTML
828
7966
22800
2026-04-14T15:43:34Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Atribut HTML]] ke [[Modul:HTML attribute]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22800
Scribunto
text/plain
return require [[Modul:HTML attribute]]
qlf0taj9fp9eoyq7ujfqqlny8yv0fzw
Modul:Bingkai
828
7967
22802
2026-04-14T15:44:24Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Bingkai]] ke [[Modul:Border]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22802
Scribunto
text/plain
return require [[Modul:Border]]
dnxkwpgn307o6aqewqe8evasu6g93w0
Modul:Bingkai/kotak pasir
828
7968
22804
2026-04-14T15:44:24Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Bingkai/kotak pasir]] ke [[Modul:Border/kotak pasir]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22804
Scribunto
text/plain
return require [[Modul:Border/kotak pasir]]
5lsv10lyy7z3eg06u5eml1wb44vbq42
Modul:Kalau kosong
828
7969
22806
2026-04-14T15:45:49Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Modul:Kalau kosong]] ke [[Modul:Module:If empty]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22806
Scribunto
text/plain
return require [[Modul:Module:If empty]]
fy665it0z3n40tzyooplejw1wqiaymx
22809
22806
2026-04-14T15:47:32Z
Hakimi97
9
Mengubah sasaran lencongan dari [[Modul:Module:If empty]] ke [[Modul:If empty]]
22809
Scribunto
text/plain
return require [[Modul:If empty]]
s12txo4ovu25cpdi5pxvw85u23bzk9b
Templat:Kalau kosong
10
7971
22811
2026-04-14T15:48:26Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Kalau kosong]] ke [[Templat:If empty]]: Penyelarasan nama dengan Wikisumber Bahasa Inggeris, untuk memudahkan tujuan penyelenggaraan
22811
wikitext
text/x-wiki
#LENCONG [[Templat:If empty]]
278jsj8u3t7cb4riank238l6izu47i5
Templat:Bingkai
10
7972
22815
2026-04-14T15:50:52Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Bingkai]] ke [[Templat:Border]] melalui lencongan
22815
wikitext
text/x-wiki
#LENCONG [[Templat:Border]]
2ug5rg9do7x2ffnnfnhhe1w6l0npfis
Templat:Bingkai/kotak pasir
10
7973
22817
2026-04-14T15:50:53Z
Hakimi97
9
Hakimi97 telah memindahkan laman [[Templat:Bingkai/kotak pasir]] ke [[Templat:Border/kotak pasir]]
22817
wikitext
text/x-wiki
#LENCONG [[Templat:Border/kotak pasir]]
cs8c99jb0gc39x0g6b7w2o0gndma85v
MediaWiki:Deletereason-dropdown
8
7974
22825
2026-04-15T04:34:45Z
Hakimi97
9
Mencipta laman baru dengan kandungan '* Sebab-sebab lazim ** Spam ** Vandalisme ** Melanggar hak cipta ** Permintaan pengarang ** Lencongan terputus ** Kod skrip yang usang'
22825
wikitext
text/x-wiki
* Sebab-sebab lazim
** Spam
** Vandalisme
** Melanggar hak cipta
** Permintaan pengarang
** Lencongan terputus
** Kod skrip yang usang
q1mw4xyi9cexsmai5xqpzmh0adqmy8w