Module:Citation/CS1/Configuration

From Chalo Chatu, Zambia online encyclopedia
Jump to navigationJump to search

{{#lst:Module:Citation/CS1/doc|header}} This configuration file contains various data that controls the functioning of Module:Citation/CS1 and hence the way that Lua-based citations are generated.

It has several sections among which are:

  1. translation tables that contain most of the literal strings that may be included in Lua-based citation. If editors are copying this Module to another wiki using a language other than English, then they should translate each of these values into that language.
  2. a list of error conditions specifying what text to display, what category to include (if any), and what help page section to refer to when errors are detected
  3. a list of ID handlers specifying the recognized document IDs, such as ISBN, DOI, etc., and how to format them.

{{#lst:Module:Citation/CS1/doc|module_components_table}}


--[[
    Module:Citation/CS1/Configuration  — Chalo Chatu hardened build
    Purpose:
      * Eliminate "attempt to index field '?' (a nil value)" fatals caused by
        missing tables or unavailable mw.ext.data (JsonConfig).
      * Keep CS1 functional even when optional data sources are absent.
      * Maintain compatibility with your existing CS1 core.

    How this works:
      1) We build (or load) a cfg table.
      2) We provide safe wrappers around mw.ext.data.get (tabular data).
      3) We "seal" cfg: ensure all critical subtables exist; inject minimal fallbacks.

    Notes:
      * This file is self-contained; no JsonConfig required.
      * If you later enable JsonConfig, this module will start using it automatically.
      * Keep CS1 core, this Configuration, and Whitelist in sync for best results.
]]--

local M = {}

----------------------------------------------------------------------
-- Safe utilities
----------------------------------------------------------------------

local function tbl(x) return type(x) == 'table' and x or {} end
local function nz(x, d) if x == nil then return d else return x end end

-- Safe wrapper for optional JsonConfig/tabular data
local function get_tabular(name)
    if mw and mw.ext and mw.ext.data and type(mw.ext.data.get) == 'function' then
        local ok, data = pcall(mw.ext.data.get, name)
        if ok and type(data) == 'table' then
            return data
        end
    end
    return nil
end

----------------------------------------------------------------------
-- Minimal defaults to prevent nil-index errors
-- These are intentionally small. CS1 will continue to work; if a key
-- is absent, the core will simply not use that feature instead of crashing.
----------------------------------------------------------------------

local FALLBACK_IETF_LANG = {
    en  = 'English',
    bem = 'Bemba',
    ny  = 'Chewa',
    loz = 'Lozi',
}

local FALLBACK_COUNTRY = {
    ZM = 'Zambia',
    US = 'United States',
    GB = 'United Kingdom',
}

-- Minimal message scaffolding (CS1 expects these subtables to exist)
local DEFAULT_MESSAGES = {
    config = { version = 'cc-hardened-2025.09' },
    error  = {},  -- specific keys are defined in CS1 core; empty is fine
    warn   = {},
    maint  = {},
}

----------------------------------------------------------------------
-- Build the configuration (rewrite)
-- If you previously had local tables here, you can copy them back into
-- the BUILD section below. The seal step will harden it regardless.
----------------------------------------------------------------------

local function build_cfg()
    local cfg = {}

    ------------------------------------------------------------------
    -- [BUILD] Core message tables and maps (safe by default)
    ------------------------------------------------------------------
    cfg.messages = DEFAULT_MESSAGES

    -- Optional tabular data; falls back to in-file maps if unavailable
    cfg.IETF_lang_map = get_tabular('Data:IETF_language_tag.tab') or FALLBACK_IETF_LANG
    cfg.country_map   = get_tabular('Data:CountryCodes.tab')      or FALLBACK_COUNTRY

    ------------------------------------------------------------------
    -- [BUILD] Aliases and parameter scaffolding
    -- We declare tables so CS1 can extend/use them without nil crashes.
    -- If your prior config defined rich alias sets, you can paste them here.
    ------------------------------------------------------------------
    cfg.aliases   = {
        -- keep tables present even if empty
        ['language'] = {},
        ['date']     = {},
        ['title']    = {},
        ['url']      = {},
        ['work']     = {},
        ['website']  = {},
        ['publisher']= {},
        ['author']   = {},
        ['chapter']  = {},
        ['edition']  = {},
        ['location'] = {},
        ['access-date'] = {},
    }

    ------------------------------------------------------------------
    -- [BUILD] Placeholders for CS1 runtime structures
    ------------------------------------------------------------------
    cfg.whitelist    = {}   -- e.g., for allowed parameters/domains (kept empty by default)
    cfg.id_handlers  = {}   -- CS1 core defines these; keep as table to avoid nil
    cfg.param_defs   = {}   -- CS1 core reads/extends definitions; keep as table
    cfg.validators   = {}   -- optional validation helpers; safe as empty
    cfg.props        = {}   -- misc properties; safe as empty
    cfg.access       = {}   -- open access labels; safe as empty
    cfg.date_formats = {}   -- date patterns; safe as empty

    return cfg
end

----------------------------------------------------------------------
-- Seal configuration: guarantee required subtables and defaults exist
----------------------------------------------------------------------

local function seal_cfg(cfg)
    cfg = tbl(cfg)

    -- Ensure top-level tables are always present
    cfg.messages     = tbl(cfg.messages)
    cfg.whitelist    = tbl(cfg.whitelist)
    cfg.id_handlers  = tbl(cfg.id_handlers)
    cfg.param_defs   = tbl(cfg.param_defs)
    cfg.aliases      = tbl(cfg.aliases)
    cfg.validators   = tbl(cfg.validators)
    cfg.props        = tbl(cfg.props)
    cfg.access       = tbl(cfg.access)
    cfg.date_formats = tbl(cfg.date_formats)

    -- Messages subtables
    cfg.messages.config = tbl(cfg.messages.config)
    cfg.messages.error  = tbl(cfg.messages.error)
    cfg.messages.warn   = tbl(cfg.messages.warn)
    cfg.messages.maint  = tbl(cfg.messages.maint)

    -- Version tag (purely informational)
    cfg.messages.config.version = nz(cfg.messages.config.version, 'cc-hardened-2025.09')

    -- Safe language/country maps
    cfg.IETF_lang_map = tbl(cfg.IETF_lang_map)
    if next(cfg.IETF_lang_map) == nil then
        cfg.IETF_lang_map = FALLBACK_IETF_LANG
    end

    cfg.country_map = tbl(cfg.country_map)
    if next(cfg.country_map) == nil then
        cfg.country_map = FALLBACK_COUNTRY
    end

    -- Ensure alias buckets exist
    local alias_buckets = {
        'language','date','title','url','work','website','publisher',
        'author','chapter','edition','location','access-date'
    }
    for _, k in ipairs(alias_buckets) do
        cfg.aliases[k] = tbl(cfg.aliases[k])
    end

    return cfg
end

----------------------------------------------------------------------
-- Build + seal + return
----------------------------------------------------------------------

local cfg = build_cfg()
return seal_cfg(cfg)