|
|
(One intermediate revision by the same user not shown) |
Line 1: |
Line 1: |
| -- This module implements [[Template:Class]], [[Template:Class/icon]] and
| |
| -- [[Template:Class/colour]].
| |
|
| |
|
| local mArguments -- lazily loaded
| |
| local definitions = mw.loadJsonData('Module:Class/definition.json')
| |
|
| |
| local p = {}
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Local configuration and messages
| |
| --------------------------------------------------------------------------------
| |
|
| |
| local cfg = {
| |
| defaultCode = 'DEFAULT',
| |
| classPrefix = 'assess-',
| |
| globalClass = 'assess',
| |
| defaultClassSuffix = 'default',
| |
| unboldClassSuffix = 'unbold',
| |
| catRootFormat = '%s %s',
| |
| catTopicFormat = '%s %s articles',
| |
| catBasicFormat = '%s articles',
| |
| categoryFormat = '[[:Category:%s|%s]]',
| |
| templateLocation = 'Template:Class',
| |
| iconTemplateLocation = 'Template:Class/icon',
| |
| colourTemplateLocation = 'Template:Class/colour',
| |
| stylesLocation = 'Module:Class/styles.css',
| |
| baseColourPath = {'colour', 'base'},
| |
| iconPath = {"icon", "file"},
| |
| iconDefaultPath = {"icon", "default"},
| |
| iconAttribPath = {"icon", "requiresAttribution"},
| |
| fullLabelPath = {"labels", "full"},
| |
| shortLabelPath = {"labels", "short"},
| |
| categoryRootPath = {"categoryRoot"},
| |
| tooltipPath = {"labels", "tooltip"},
| |
| yes = "yes",
| |
| no = "no",
| |
| argumentNames = {
| |
| class = "class",
| |
| style = "style"
| |
| },
| |
| getOptions = {
| |
| --First item is localized argument name, second is case-sensitivity
| |
| bold = {"bold", false},
| |
| header = {"header", false},
| |
| image = {"image", false},
| |
| rowspan = {"rowspan", false},
| |
| fullcategory = {"fullcategory", true},
| |
| category = {"category", true},
| |
| topic = {"topic", true}
| |
| }
| |
| }
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Argument helper functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| local function getRawArgs(frame, wrapper)
| |
| --Retrieves the arguments from the frame
| |
| mArguments = mArguments or require('Module:Arguments')
| |
| return mArguments.getArgs(frame, {
| |
| wrappers = wrapper,
| |
| trim = false,
| |
| removeBlanks = false
| |
| })
| |
| end
| |
|
| |
| local function makeInvokeFunction(func, wrapper)
| |
| --Wraps a general function into an invokable version
| |
| return function (frame)
| |
| local args = getRawArgs(frame, wrapper)
| |
| return func(args)
| |
| end
| |
| end
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- String helper functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| local function trim(str)
| |
| --Trims strings, passes through non-strings without modification
| |
| return (type(str) == 'string') and mw.text.trim(str) or str
| |
| end
| |
|
| |
| local function normalizeValue(val)
| |
| --Normalizes strings, particularly class codes
| |
| if type(val) == 'string' then val = trim(val):lower() end
| |
| if val == '' then val = nil end
| |
| return val
| |
| end
| |
|
| |
| local function ucfirst(str)
| |
| --Capitalizes the first character of a string
| |
| return mw.ustring.upper(mw.ustring.sub(str, 1, 1)) .. mw.ustring.sub(str, 2)
| |
| end
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Definition helper functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| local function getDefinition(code)
| |
| --Retrieves the definition and canonical class code for a given code.
| |
| --Returns two values: the definition object and the canonical class code
| |
| --string.
| |
| local canonicalCode = normalizeValue(code)
| |
| if code == cfg.defaultCode then canonicalCode = code end
| |
| local class = definitions[canonicalCode]
| |
| while class and class.alias do
| |
| canonicalCode = class.alias
| |
| class = definitions[class.alias]
| |
| end
| |
| if not class then
| |
| return nil, nil
| |
| end
| |
| return class, canonicalCode
| |
| end
| |
|
| |
| local function getDefault()
| |
| --Shortcut function for retrieving the default definition
| |
| return getDefinition(cfg.defaultCode) end
| |
|
| |
| local function getProperty(class, default, map)
| |
| --Retrieves a given property from a string given a class definition, a
| |
| --default class definition, and a map for the path to traverse through the
| |
| --class object. The map should be a sequential table of string property
| |
| --names, e.g. {"colour", "base"} would retrieve someClass.colour.base
| |
| local prop, dProp = class, default
| |
| for k, v in ipairs(map) do
| |
| prop = ((type(prop) == 'table') or nil) and prop[v]
| |
| dProp = ((type(dProp) == 'table') or nil) and dProp[v]
| |
| end
| |
| if prop == nil then prop = dProp end
| |
| return prop
| |
| end
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Color functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| function p._colour(code)
| |
| --Retrieves the base colour for a given code
| |
| return getProperty(getDefinition(code), getDefault(), cfg.baseColourPath)
| |
| end
| |
|
| |
| function p.colour(frame)
| |
| --Retrieves the base colour for a given code; is invokable
| |
| local args = getRawArgs(frame, cfg.colourTemplateLocation)
| |
| -- Nowiki tags prevent output beginning with "#" from triggering bug 14974.
| |
| return frame:extensionTag('nowiki', p._colour(args[1]))
| |
| end
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Icon functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| function p._icon(args)
| |
| --Retrieves an icon image and formats it as wikitext
| |
| local class = getDefinition(args[cfg.argumentNames.class] or args[1])
| |
| local default = getDefault()
| |
| local file = getProperty(class, default, cfg.iconPath)
| |
| local label =
| |
| getProperty(class, default, cfg.tooltipPath) or
| |
| ucfirst(getProperty(class, default, cfg.fullLabelPath))
| |
| local attrib = getProperty(class, default, cfg.iconAttribPath)
| |
| local size = args.size or '16px'
| |
| local span = mw.html.create('span')
| |
|
| |
| span
| |
| :cssText(args[cfg.argumentNames.style])
| |
| :attr('title', label)
| |
| :wikitext(
| |
| string.format(
| |
| '[[File:%s|%s|' .. size .. '%s|class=noviewer|alt=]]',
| |
| file,
| |
| label,
| |
| attrib and '' or '|link='
| |
| )
| |
| )
| |
| return tostring(span)
| |
| end
| |
|
| |
| p.icon = makeInvokeFunction(p._icon, cfg.iconTemplateLocation)
| |
| --Invokable version of p._icon
| |
|
| |
| --------------------------------------------------------------------------------
| |
| -- Class functions
| |
| --------------------------------------------------------------------------------
| |
|
| |
| function p._class(args)
| |
| --Parses its arguments into a table cell with an optional icon, a name
| |
| --linked to an appropriate category, and appropriate colour styling
| |
| local classDef, classCode =
| |
| getDefinition(args[cfg.argumentNames.class] or args[1])
| |
| local default = getDefault()
| |
| local iconDefault = getProperty(classDef, default, cfg.iconDefaultPath)
| |
| local shortLabel = getProperty(classDef, default, cfg.shortLabelPath)
| |
| local categoryRoot = getProperty(classDef, default, cfg.categoryRootPath)
| |
| --o is short for "options", go for "get options". Bool true → case-sensitive
| |
| local o, go = {}, cfg.getOptions
| |
| for k, v in pairs(go) do
| |
| o[k] = v[2] and trim(args[v[1]]) or normalizeValue(args[v[1]])
| |
| end
| |
|
| |
| local cell = mw.html.create(o.header and 'th' or 'td')
| |
| --image=yes forces icon, image=no disables it, otherwise checks default
| |
| local icon = iconDefault and (o.image ~= cfg.no) or (o.image == cfg.yes)
| |
| icon = icon and p.icon(args) .. ' ' or ''
| |
|
| |
| local category
| |
| if o.fullcategory then
| |
| category = o.fullcategory
| |
| elseif o.category then
| |
| category = string.format(cfg.catRootFormat, categoryRoot, o.category)
| |
| elseif o.topic then
| |
| category = string.format(cfg.catTopicFormat, categoryRoot, o.topic)
| |
| else
| |
| category = string.format(cfg.catBasicFormat, categoryRoot)
| |
| end
| |
| local text = string.format(cfg.categoryFormat, category, shortLabel)
| |
| cell
| |
| :addClass(cfg.globalClass)
| |
| :addClass(
| |
| o.bold == cfg.no and cfg.classPrefix .. cfg.unboldClassSuffix or nil
| |
| )
| |
| :addClass(cfg.classPrefix .. (classCode or cfg.defaultClassSuffix))
| |
| :attr('rowspan', tonumber(o.rowspan))
| |
| :wikitext(mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = {src = cfg.stylesLocation} }, icon, text)
| |
|
| |
| return tostring(cell)
| |
| end
| |
|
| |
| p.class = makeInvokeFunction(p._class, cfg.templateLocation)
| |
| --Invokable version of p._class
| |
|
| |
| return p
| |