Documentation for this module may be created at Module:Format/doc

--------------------------------------------------------------------------------
-- Module:Format
-- Simple formatting utilities for inline and block-level elements.
--
-- INSTALLATION:
-- 1. Create page: Module:Format
-- 2. Paste this entire file
-- 3. Create TemplateStyles page: Module:Format/styles.css
--
-- USAGE:
-- {{#invoke:Format|abbr|abbreviation|full text}}
-- {{#invoke:Format|nowrap|text that should not wrap}}
-- {{#invoke:Format|lang|fr|Bonjour}}
-- {{#invoke:Format|sic}}
-- {{#invoke:Format|clear}}
--
-- @author Remilia Wiki
-- @license MIT
--------------------------------------------------------------------------------

local p = {}

--------------------------------------------------------------------------------
-- UTILITY FUNCTIONS
--------------------------------------------------------------------------------

local function trim(s)
    if not s then return nil end
    return tostring(s):match("^%s*(.-)%s*$")
end

local function isEmpty(s)
    if s == nil then return true end
    if type(s) == 'string' then
        return trim(s) == ''
    end
    return false
end

local function hasValue(s)
    return not isEmpty(s)
end

local function getArg(args, name, default)
    local val = args[name]
    if isEmpty(val) then return default end
    return trim(val)
end

local function getFrameArgs(frame)
    local args = {}
    local parentArgs = frame:getParent() and frame:getParent().args or {}
    local directArgs = frame.args or {}
    for k, v in pairs(directArgs) do args[k] = v end
    for k, v in pairs(parentArgs) do args[k] = v end
    return args
end

--------------------------------------------------------------------------------
-- ABBREVIATION
--------------------------------------------------------------------------------

function p.abbr(frame)
    local args = getFrameArgs(frame)

    local abbr = getArg(args, 1)
    local title = getArg(args, 2) or getArg(args, 'title')

    if isEmpty(abbr) then
        return '<span class="error">Error: Abbreviation required</span>'
    end

    local span = mw.html.create('abbr')
        :addClass('abbr')

    if hasValue(title) then
        span:attr('title', title)
    end

    span:wikitext(abbr)

    return tostring(span)
end

--------------------------------------------------------------------------------
-- NOWRAP
--------------------------------------------------------------------------------

function p.nowrap(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1)
    if isEmpty(text) then
        return ''
    end

    local span = mw.html.create('span')
        :addClass('nowrap')
        :wikitext(text)

    return tostring(span)
end

--------------------------------------------------------------------------------
-- LANGUAGE MARKUP
--------------------------------------------------------------------------------

function p.lang(frame)
    local args = getFrameArgs(frame)

    local code = getArg(args, 1) or getArg(args, 'code')
    local text = getArg(args, 2) or getArg(args, 'text')

    if isEmpty(text) then
        return '<span class="error">Error: Text required</span>'
    end

    local span = mw.html.create('span')
        :addClass('lang')

    if hasValue(code) then
        span:attr('lang', code)
        span:addClass('lang-' .. code)
    end

    span:wikitext(text)

    return tostring(span)
end

--------------------------------------------------------------------------------
-- SIC
--------------------------------------------------------------------------------

function p.sic(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1)
    local reason = getArg(args, 'reason')

    local result = ''

    if hasValue(text) then
        result = text
    end

    local span = mw.html.create('span')
        :addClass('sic')
        :addClass('noprint')

    if hasValue(reason) then
        span:attr('title', reason)
    end

    span:wikitext('[<i>sic</i>]')

    return result .. tostring(span)
end

--------------------------------------------------------------------------------
-- CLEAR
--------------------------------------------------------------------------------

function p.clear(frame)
    local args = getFrameArgs(frame)

    local side = getArg(args, 1, 'both')

    local div = mw.html.create('div')
        :addClass('clear')

    if side == 'left' then
        div:addClass('clear-left')
    elseif side == 'right' then
        div:addClass('clear-right')
    else
        div:addClass('clear-both')
    end

    return tostring(div)
end

--------------------------------------------------------------------------------
-- BLOCK INDENT
--------------------------------------------------------------------------------

function p.indent(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1) or getArg(args, 'text')
    local level = tonumber(getArg(args, 'level', '1')) or 1

    if isEmpty(text) then
        return ''
    end

    local div = mw.html.create('div')
        :addClass('block-indent')
        :addClass('indent-' .. level)
        :wikitext(text)

    return tostring(div)
end

--------------------------------------------------------------------------------
-- EMPHASIS
--------------------------------------------------------------------------------

function p.em(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1)
    if isEmpty(text) then
        return ''
    end

    local em = mw.html.create('em')
        :wikitext(text)

    return tostring(em)
end

--------------------------------------------------------------------------------
-- STRONG
--------------------------------------------------------------------------------

function p.strong(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1)
    if isEmpty(text) then
        return ''
    end

    local strong = mw.html.create('strong')
        :wikitext(text)

    return tostring(strong)
end

--------------------------------------------------------------------------------
-- ANCHOR
--------------------------------------------------------------------------------

function p.anchor(frame)
    local args = getFrameArgs(frame)

    local name = getArg(args, 1) or getArg(args, 'name')
    if isEmpty(name) then
        return ''
    end

    local span = mw.html.create('span')
        :attr('id', name)

    return tostring(span)
end

--------------------------------------------------------------------------------
-- UNBULLETED LIST
--------------------------------------------------------------------------------

function p.unbulleted(frame)
    local args = getFrameArgs(frame)

    local ul = mw.html.create('ul')
        :addClass('unbulleted-list')

    for i = 1, 30 do
        local item = getArg(args, i)
        if hasValue(item) then
            ul:tag('li'):wikitext(item)
        end
    end

    return tostring(ul)
end

--------------------------------------------------------------------------------
-- PLAINLIST
--------------------------------------------------------------------------------

function p.plainlist(frame)
    local args = getFrameArgs(frame)

    local content = getArg(args, 1) or getArg(args, 'content')
    if isEmpty(content) then
        return ''
    end

    local div = mw.html.create('div')
        :addClass('plainlist')
        :wikitext(content)

    return tostring(div)
end

--------------------------------------------------------------------------------
-- CIRCA
--------------------------------------------------------------------------------

function p.circa(frame)
    local args = getFrameArgs(frame)

    local date = getArg(args, 1)
    local lc = getArg(args, 'lc') == 'yes' or getArg(args, 'lc') == 'y'

    local prefix = lc and 'c.' or 'C.'

    local abbr = mw.html.create('abbr')
        :attr('title', 'circa')
        :wikitext(prefix)

    local result = tostring(abbr)

    if hasValue(date) then
        result = result .. '&thinsp;' .. date
    end

    return result
end

--------------------------------------------------------------------------------
-- IPA
--------------------------------------------------------------------------------

function p.ipa(frame)
    local args = getFrameArgs(frame)

    local text = getArg(args, 1)
    if isEmpty(text) then
        return ''
    end

    local span = mw.html.create('span')
        :addClass('ipa')
        :attr('title', 'Representation in the International Phonetic Alphabet')
        :wikitext('/' .. text .. '/')

    return tostring(span)
end

--------------------------------------------------------------------------------
-- APOSTROPHE (after italics)
--------------------------------------------------------------------------------

function p.apostrophe(frame)
    -- Returns a properly formatted apostrophe that won't be
    -- interpreted as wiki italic markup
    return "<span class=\"apostrophe\">'</span>"
end

--------------------------------------------------------------------------------
-- APOSTROPHE-S (possessive after italics)
--------------------------------------------------------------------------------

function p.apostrophe_s(frame)
    -- Returns a properly formatted possessive 's that won't be
    -- interpreted as wiki italic markup
    return "<span class=\"apostrophe\">'s</span>"
end

--------------------------------------------------------------------------------
-- MATH (inline mathematical expression)
--------------------------------------------------------------------------------

function p.math(frame)
    local args = getFrameArgs(frame)

    local expr = getArg(args, 1)
    if isEmpty(expr) then
        return ''
    end

    local span = mw.html.create('span')
        :addClass('texhtml')
        :wikitext(expr)

    return tostring(span)
end

--------------------------------------------------------------------------------
-- GALLERY (wrapper for MediaWiki gallery tag)
--------------------------------------------------------------------------------

function p.gallery(frame)
    local args = getFrameArgs(frame)

    local content = getArg(args, 1)
    if isEmpty(content) then
        return ''
    end

    return '<gallery>\n' .. content .. '\n</gallery>'
end

return p