Jump to content

Module:Year in various calendars

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mr. Stradivarius (talk | contribs) at 03:59, 16 August 2013 (initial version, object-oriented approach). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

local htmlBuilder = require( 'Module:HtmlBuilder' )

--------------------------------------------------------------------
-- Calendar box class definition
--------------------------------------------------------------------

local calendarBox = {}
calendarBox.__index = calendarBox

function calendarBox:new( init )
    init = type( init ) == 'table' and init or {}
    local title = mw.title.getCurrentTitle()
    local obj = {}
    
    -- Set the year. Use the specified year if it is valid, otherwise use the current year.
    local initYear = tonumber( init.year )
    if initYear and math.floor( initYear ) == initYear and initYear ~= math.huge then
        self.year = initYear
    else
        self.year = tonumber( mw.language.getContentLanguage():formatDate( 'Y' ) )
    end
    
    self.caption = init[ 1 ] == 'BC' and title.text or self.year

    return setmetatable( obj, {
        __index = self
    })
end    

function calendarBox:addCalendar( obj )
    if not ( type( obj ) == 'table' ) then
        error( 'invalid calendar object "' .. obj .. '" passed to addCalendar' )
    end
    self.calendars = self.calendars or {}
    table.insert( self.calendars, obj )
end

calendarBox.addCalendarGroup = calendarBox.addCalendar

function calendarBox:export()
    local root = htmlBuilder.create( 'table' )
    root
        .addClass( 'infobox' )
        .addClass( 'vevent' )
        .css( 'width', '22em' )
        .tag( 'caption' )
            .css( 'font-size', '125%' )
            .tag( 'span' )
                .addClass( 'summary' )
                .addClass( 'dtstart' )
                .wikitext( self.caption )

    --local row = root.tag( 'tr' )
    for i, calendar in ipairs( self.calendars ) do
        root
            .tag( 'tr' )
                .tag( 'td' )
                    .wikitext( calendar.link )
                    .done()
                .tag( 'td' )
                    .wikitext( calendar.calculateYear( self.year ) )
                    .allDone()
    end

    return tostring( root )
end

--------------------------------------------------------------------
-- Calendar group class definition
--------------------------------------------------------------------

--  Calendar groups are used to group different calendars together. 
--  Previously, the template did this by including a table row with
--  no year value. By using objects we can do the same thing more
--  semantically.

local calendarGroup = {}
calendarGroup.__index = calendarGroup
calendarGroup.type = 'calendarGroup'

function calendarGroup:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}
    obj.heading = init.heading
    obj.calendars = init.calendars
    return setmetatable( obj, {
        __index = self
    })
end

--------------------------------------------------------------------
-- Calendar class definition
--------------------------------------------------------------------

local calendar = {}
calendar.__index = calendar
calendar.type = 'calendar'

function calendar:new()
    local obj = {}
    return setmetatable( obj, {
        __index = self
    })
end

function calendar:setLink( link, display, italics )
    if not type( link ) == 'string' then
        return nil
    end
    display = type( display ) == 'string' and display 
    local ret
    if display then
        ret = mw.ustring.format( '[[%s|%s]]', link, display )
    else
        ret = mw.ustring.format( '[[%s]]', link )
    end
    if italics then
        ret = mw.ustring.format( "''%s''", ret )
    end
    self.link = ret
end

function calendar:setYearFunction( func )
    self.calculateYear = func
end

--------------------------------------------------------------------
-- Build the box
--------------------------------------------------------------------

local function _main( args )
    local box = calendarBox:new( args )

    -- Gregorian calendar

    local gregorian = calendar:new()
    gregorian:setLink( 'Gregorian calendar' )
    gregorian:setYearFunction(
        function( year )
            return year
        end
    )
    box:addCalendar( gregorian )
            
    -- Ab urbe condita
    
    local abUrbe = calendar:new()
    abUrbe:setLink( 'Ab urbe condita' )
    abUrbe:setYearFunction(
        function( year )
            return year + 753
        end
    )
    box:addCalendar( abUrbe )
    
    return box:export()
end

--------------------------------------------------------------------
-- Output the box and the class definitions
--------------------------------------------------------------------

local p = {}

function p.main( frame )
    -- If called via #invoke, use the args passed into the invoking
    -- template, or the args passed to #invoke if any exist. Otherwise
    -- assume args are being passed directly in from the debug console
    -- or from another Lua module.
    local origArgs
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
        for k, v in pairs( frame.args ) do
            origArgs = frame.args
            break
        end
    else
        origArgs = frame
    end
    -- Trim whitespace and remove blank arguments.
    local args = {}
    for k, v in pairs( origArgs ) do
        if type( v ) == 'string' then
            v = mw.text.trim( v )
        end
        if v ~= '' then
            args[k] = v
        end
    end
    return _main( args )
end

p.calendarBox = calendarBox
p.calendarGroup = calendarGroup
p.calendar = calendar

return p