Roovet Articles

Module:Citation/CS1/Utilities

{{#lst:Module:Citation/CS1/doc|header}} This page contains various functions and tables that are common to multiple of the various modules that make up Module:Citation/CS1.

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


-- Module:Citation/CS1/Utilities (compact, compatible)
-- Provides the utility functions CS1 expects + set_selected_modules()

local U = {}
local cfg -- set in set_selected_modules()

-- public state shared with CS1
local z = {
  error_categories = {},
  maintenance_cats = {},
  message_tail     = {},
  prop_keys_t      = {}, -- used when making class attributes; empty is fine
}
U.z = z

-- helpers
local function is_set(v) return not (v == nil or v == '') end
local function substitute(msg, args)
  if not msg then return '' end
  if type(args) == 'table' then
    -- $1, $2... replacement
    for i = 1, #args do
      msg = msg:gsub('%$'..i, tostring(args[i] or ''))
    end
  end
  return msg
end

-- Minimal styling hooks used by CS1
local function wrap_style(key, str)
  if not is_set(str) then return '' end
  local pres = (cfg and cfg.presentation) or {}
  local tpl  = pres[key]
  if tpl then return substitute(tpl, {str}) end
  return str
end

-- Error display wrapper (hidden vs visible)
local function error_comment(content, hidden)
  local pres = (cfg and cfg.presentation) or {}
  if hidden and pres['hidden-error'] then
    return substitute(pres['hidden-error'], {content})
  end
  if pres['visible-error'] then
    return substitute(pres['visible-error'], {content})
  end
  return content
end

-- Collects an error message by key; very lightweight
local function set_message(key, args)
  local msgs = (cfg and cfg.messages) or {}
  local text = msgs[key] or key
  text = substitute(text, args)
  table.insert(z.message_tail, { error_comment(text, false) })
  return text
end

-- Commonly used functions
local function in_array(needle, haystack)
  if needle == nil or type(haystack) ~= 'table' then return false end
  for i, v in ipairs(haystack) do if v == needle then return i end end
  return false
end

local function safe_for_italics(str)
  if not is_set(str) then return str end
  if str:sub(1,1) == "'" then str = "<span></span>" .. str end
  if str:sub(-1) == "'" then str = str .. "<span></span>" end
  return str:gsub('\n', ' ')
end

local function make_wikilink(link, display)
  if not is_set(link) then return '' end
  if is_set(display) then return '[['..link..'|'..display..']]' end
  return '[['..link..']]'
end

local function remove_wiki_link(str)
  return (str:gsub("%[%[([^%[%]]*)%]%]", function(l)
    return l:gsub("^[^|]*|(.*)$", "%1"):gsub("^%s*(.-)%s*$","%1")
  end))
end

local function is_wikilink(str)
  local D, L
  local wl_type = 2
  L, D = str:match('%[%[([^|]+)|([^%]]+)%]%]')
  if not is_set(D) then
    D = str:match('%[%[([^%]]*)|*%]%]')
    wl_type = 1
  end
  if not is_set(D) then D = str; wl_type = 0 end
  if mw and mw.text then
    D = mw.text.trim(D, '%s|')
    L = L and mw.text.trim(L, '%s|')
  end
  return wl_type, D, L or ''
end

-- alias selection helper used in a few places
local function is_alias_used(args, alias, index, enumerated, value, selected, error_list)
  if enumerated then alias = alias:gsub('#', index) else alias = alias:gsub('#', '') end
  if is_set(args[alias]) then
    if value ~= nil and selected ~= alias then
      local dup
      for _, v in ipairs(error_list) do if v == alias then dup = true break end end
      if not dup then table.insert(error_list, alias) end
    else
      value = args[alias]; selected = alias
    end
  end
  return value, selected
end

local function select_one(args, aliases_list, error_condition, index)
  local value, selected, error_list = nil, '', {}
  if index ~= nil then index = tostring(index) end
  for _, alias in ipairs(aliases_list or {}) do
    if alias:match('#') then
      if '1' == index then value, selected = is_alias_used(args, alias, index, false, value, selected, error_list) end
      value, selected = is_alias_used(args, alias, index, true, value, selected, error_list)
    else
      value, selected = is_alias_used(args, alias, index, false, value, selected, error_list)
    end
  end
  -- We keep error reporting very light; CS1 proper will add details
  return value, selected
end

-- Maintenance category collector (safe no-op)
local added_maint_cats = {}
local function add_maint_cat(key, arguments)
  local maint = (cfg and cfg.maint_cats) or {}
  if not added_maint_cats[key] and maint[key] then
    added_maint_cats[key] = true
    table.insert(z.maintenance_cats, substitute(maint[key], arguments))
  end
end

-- export minimal error setter used by CS1
local function set_error(error_id, arguments, raw, prefix, suffix)
  local messages = (cfg and cfg.messages) or {}
  local err = messages[error_id] or error_id
  local msg = substitute(err, arguments)
  msg = (prefix or '') .. msg .. (suffix or '')
  table.insert(z.message_tail, { error_comment(msg, false) })
  return msg, false
end

-- required by CS1 init step
function U.set_selected_modules(cfg_ptr)
  cfg = cfg_ptr
end

-- exports
U.is_set = is_set
U.in_array = in_array
U.substitute = substitute
U.error_comment = error_comment
U.set_message = set_message
U.set_error = set_error
U.select_one = select_one
U.add_maint_cat = add_maint_cat
U.wrap_style = wrap_style
U.safe_for_italics = safe_for_italics
U.remove_wiki_link = remove_wiki_link
U.is_wikilink = is_wikilink
U.make_wikilink = make_wikilink

return U