Hopp til innhold

Modul:Header template

Fra Wikikilden

Dokumentasjon for denne modulen kan opprettes på Modul:Header template/dok

function cleanCoinsParameter( param )
    param = string.gsub( param, "%[%[.*|(.*)%]%]", "%1" )
    return string.gsub( param, "%[%[(.*)%]%]", "%1" )
end


function formatString( str, schema_property )
    return tostring(mw.html.create('span')
        :attr('itemprop', schema_property)
        :wikitext(str)
    )
end

function formatYear( date, schema_property )
    year = tonumber( date )
    if year == nil or year < 1000 then
        return tostring(mw.html.create('span')
            :attr('itemprop', schema_property)
            :wikitext(date))
    else
        return tostring(mw.html.create('time')
            :attr('datetime', year)
            :attr('itemprop', schema_property)
            :wikitext(date))
    end
end


function formatPublisherWithName( name )
    return tostring(mw.html.create('span')
        :attr('itemprop', 'publisher')
        :attr('itemscope', '')
        :attr('itemtype', 'http://schema.org/Organization') --TODO: always an Organization?
        :tag('span')
            :attr('itemprop', 'name')
            :wikitext(name)
            :done()
    )
end


function formatAuthorLink( page, label, schema_property )
    -- TODO: itemid quand on pourra répérer les ids Wikidata https://phabricator.wikimedia.org/T152909
    local title = mw.title.new( page )
    if title == nil then
    	return tostring(mw.html.create('span')
        	:attr('itemprop', schema_property)
        	:attr('itemscope', '')
        	:attr('itemtype', 'http://schema.org/Person') --TODO: not always true (but nearly)
        	:wikitext('[[' .. page .. '|<span itemprop="name">' .. label .. '</span>]]')
    	)
    end
    if title.isRedirect then
        title = title.redirectTarget
    end
    return tostring(mw.html.create('span')
        :attr('itemprop', schema_property)
        :attr('itemscope', '')
        :attr('itemtype', 'http://schema.org/Person') --TODO: not always true (but nearly)
        :wikitext('[[' .. title.fullText .. '|<span itemprop="name">' .. label .. '</span>]]')
        :tag('link')
            :attr('itemprop', 'url')
            :attr('href', title:fullUrl(nil, 'canonical'))
            :done()
    )
end


function parseAuthorWikitext( wikitext, schema_property )
	wikitext = mw.ustring.gsub( wikitext, '%[%[([^|]*)|(.*)%]%]', function( page, link )
        return formatAuthorLink( page, link, schema_property )
    end )
    wikitext = mw.ustring.gsub( wikitext, '%[%[([^|]*)%]%]', function( page )
        return formatAuthorLink( page, page, schema_property )
    end )
    return wikitext
end


function formatTitleLink( page, label, schema_property )
    -- TODO: itemid quand on pourra répérer les ids Wikidata https://phabricator.wikimedia.org/T152909
    local title = mw.title.new( page )
    if title == nil then
    	return '[[' .. page .. '|' .. label .. ']]'
    end
    if title.isRedirect then
        title = title.redirectTarget
    end
    return tostring(mw.html.create('span')
        :attr('itemprop', schema_property)
        :attr('itemscope', '')
        :attr('itemtype', 'http://schema.org/CreativeWork') --TODO: find a more relenvant type
        :wikitext('[[' .. title.fullText .. '|<span itemprop="name">' .. label .. '</span>]]')
        :tag('link')
            :attr('itemprop', 'url')
            :attr('href', title:fullUrl(nil, 'canonical'))
            :done()
    )
end


function parseTitleWikitext( wikitext, schema_property )
    wikitext = mw.ustring.gsub( wikitext, '%[%[([^|]*)|(.*)%]%]', function( page, link )
        return formatTitleLink( page, link, schema_property )
    end )
    wikitext = mw.ustring.gsub( wikitext, '%[%[([^|]*)%]%]', function( page )
        return formatTitleLink( page, page, schema_property )
    end )
    return wikitext
end


function headerTemplate( frame )
    local parentFrame = frame:getParent()
    local args = parentFrame.args
    local page = mw.title.getCurrentTitle()
    local item = mw.wikibase.getEntity()
    local headerType = args.value
    if args.header_type and args.header_type ~= '' then
        headerType = args.header_type
    end

    headerType = mw.ustring.lower( headerType ) --Permet d'écrire le type en majuscule ou en minuscule
    local erSammendrag = (headerType == 'sammendrag' or headerType == 'toc')

    --Custom page numbers
    local from = ''
    if args.displayed_from and args.displayed_from ~= '' then
        from = args.displayed_from
    elseif args.from then
        from = args.from
    end

    local to = ''
    if args.displayed_to and args.displayed_to ~= '' then
        to = args.displayed_to
    elseif args.to then
        to = args.to
    end
    local schema_type = 'http://schema.org/CreativeWork'
    if args.type then
        if args.type == 'book' then
            if erSammendrag then
                schema_type = 'http://schema.org/Book'
            else
                schema_type = 'http://schema.org/Chapter'
            end
        elseif args.type == 'collection' then
            -- TODO: compliqué
        elseif args.type == 'journal' then
            if not erSammendrag then
                schema_type = 'http://schema.org/Article'
            end
        elseif args.type == 'phdthesis' then
            if erSammendrag then
                schema_type = 'http://schema.org/Thesis'
            else
                schema_type = 'http://schema.org/Chapter'
            end
        end
    end

    --Début du header
    local html = mw.html.create()
    local container = html:tag('div')
        :attr('itemscope', '')
        :attr('itemtype', schema_type)
    if item ~= nil then
        container:attr('itemid', 'http://www.wikidata.org/entity/' .. item.id)
    end

    classement( parentFrame, page, args )
    if args.header_type == 'empty' then
        if args.sammendrag then
            container:tag( 'div' )
                :addClass('ws-summary')
                :css('margin-top', '1em')
                :newline()
                :wikitext(args.sammendrag)
        end
        return html
    end

    local headertemplate = container:tag('div')
        :attr('id', 'headertemplate')
        :addClass('ws-noexport')
        :tag('div')
    
    if args.type == 'journal' then
        headertemplate:addClass('headertemplate-journal')
    else
        headertemplate:addClass('headertemplate')
    end

    --Forfatter
    if args.forfatter and args.forfatter ~= '' then
        headertemplate:tag('div')
            :addClass('headertemplate-author')
            :wikitext(parseAuthorWikitext(args.forfatter, 'author'))
    end

    --Titre
    local tittel = formatString( page.baseText, 'name' )
    if args.type == 'collection' then
        if args.samling and args.samling ~= '' then
            -- Commenté pour tester avec uniquement le nom du recueil, le titre lui est déjà
            -- dans le navigateur et fréquemment en début de la page.
            -- tittel = tittel .. '&#32;— <i>' .. args.samling .. '</i>'
             tittel = '<i>' .. parseTitleWikitext(args.samling, 'isPartOf') .. '</i>'
        elseif args.current then
            tittel = formatString( args.current, 'name' )
        else
        	if erSammendrag then
        		tittel = formatString( tittel, 'name' )
    		else
    			tittel = parseTitleWikitext(tittel, 'isPartOf')
	    	end
	    end

        if args.publication and args.publication ~= '' then
            tittel = tittel .. ' <span style="font-size:90%;">(' .. args.publication .. ')</span>'
        end
    elseif args.type == 'journal' then
        if erSammendrag then
            tittel = formatString( args.tittel, 'name' )
        elseif args.current then
            tittel = formatString( args.current, 'name' )
        else
        	tittel = parseTitleWikitext(tittel, 'isPartOf')
       	end
    else
        if args.tittel then
        	tittel = args.tittel
        end
        if erSammendrag then
        	tittel = formatString( tittel, 'name' )
    	else
    		tittel = parseTitleWikitext(tittel, 'isPartOf')
	    end
        if args.publication and args.publication ~= '' then
            tittel = tittel .. ' <span style="font-size:90%;">(' .. args.publication .. ')</span>'
        end
    end
    if erSammendrag and args['undertittel'] and args['undertittel'] ~= '' then
       tittel = tittel .. ' <br/><small>' .. args['undertittel'] .. '</small>'
    end
	headertemplate:tag('div')
		:addClass('headertemplate-title')
	    :wikitext(tittel)

    --References
    local references = headertemplate:tag('div')
        :addClass('headertemplate-reference')
    if args.oversetter and args.oversetter ~= '' then
        references:wikitext('Oversatt av ' .. parseAuthorWikitext(args.oversetter, 'translator') .. '.')
            :tag('br')
    end
    if erSammendrag and args.illustrator and args.illustrator ~= '' then
        references:wikitext('Illustrert av ' .. parseAuthorWikitext(args.illustrator, 'illustrator') .. '.')
            :tag('br')
    end

    if erSammendrag and args.bind and args.bind ~= '' then
        references:wikitext( formatString( args.bind, 'volumeNumber' ) )
            :tag('br')
    end

    local infos = {} --Liste des données à afficher séparés par une virgule
    if args.type == 'collection' then
        if args.tittel and args.tittel ~= '' then
            table.insert( infos, '<i>' .. args.tittel .. '</i>' )
        end
        if args.utgiver and args.utgiver ~= '' then
            table.insert( infos, 'Utgitt av ' .. parseAuthorWikitext( args.utgiver, 'editor' ) )
        end
        if args.forlag and args.forlag ~= '' then
            table.insert( infos, formatPublisherWithName( args.forlag ) )
        end
        if args.ar and args.ar ~= '' then
            table.insert( infos, formatYear( args.ar, 'datePublished' ) )
        end
        if not erSammendrag then
            if args.bind and args.bind ~= '' then
                table.insert( infos, formatString( args.bind, 'volumeNumber' ) )
            end
        end
    elseif args.type == 'journal' then
        if not erSammendrag then
            table.insert( infos, '<i>' .. args.tittel .. '</i>' )
            if args.bind and args.bind ~= '' then
                table.insert( infos, formatString( args.bind, 'volumeNumber' ) )
            end
        end
        if args.ar and args.ar ~= '' then
            table.insert( infos, formatYear( args.ar, 'datePublished' ) )
        end
    else
        if args.utgiver and args.utgiver ~= '' then
            table.insert( infos, 'Utgitt av ' .. parseAuthorWikitext( args.utgiver, 'editor' ) )
        end
        if args.forlag and args.forlag ~= '' then
            table.insert( infos, formatPublisherWithName( args.forlag ) )
        end
        if args.ar and args.ar ~= '' then
            table.insert( infos, formatYear( args.ar, 'datePublished' ) )
        end
    end
    local line = ''
    if infos ~= {} then
        line = table.concat( infos, ',&nbsp;' )
    end

    --Parenthèse
    if not erSammendrag and from ~= '' then
        local temp = ''
        if args.bind and args.bind ~= '' and args.type ~= 'collection' and args.type ~= 'journal' then
            temp = formatString( args.bind, 'volumeNumber' ) .. ',&nbsp;'
        end
        if from ~= to or from ~= '-' then
            temp = temp .. pagination( from, to )
        end

        if temp ~= '' then
            line = line .. ' (' .. temp .. ')'
        end
    end

    if line ~= '' then
        references:wikitext(line .. '.')
    end

    local subheader = container:tag('div')
        :attr('id', 'subheader')
        :addClass('ws-noexport')
        :css('margin-bottom', '1.5em')
    if erSammendrag then
        local texteEntier = mw.title.new( page.prefixedText .. '/Texte entier' )
        if texteEntier and texteEntier.exists then
            subheader:tag('div')
                :css('text-align', 'center')
                :wikitext('[[' .. texteEntier.fullText .. '|Texte sur une seule page]]')
        end
    end

    if (not erSammendrag or (args.header_type and args.header_type =='toc')) and ((args.prev and args.prev ~= '') or (args.next and args.next ~= '')) then
        local maxwidth = 50
        if args.current and args.current ~= '' then
            maxwidth = 33
        end
        local footer = subheader:tag('div')
            :addClass('footertemplate')
            :addClass('ws-noexport')
        local nav = footer:tag('div')
            :css('width', '100%')
            :css('padding-left', '0px')
            :css('padding-right', '0px')
            :css('background-color', 'transparent')
        if args.prev and args.prev ~= '' then
            nav:tag('div')
                :css('text-align', 'left')
                :css('float', 'left')
                :css('max-width', maxwidth .. '%')
                :tag('span')
                    :attr('id', 'headerprevious')
                    :tag('span')
                        :css('color', '#808080')
                        :wikitext('&#x25C4;&nbsp;&nbsp;')
                        :done()
                    :wikitext(args.prev)
        end
        if args.next and args.next ~= '' then
            nav:tag('div')
                :css('text-align', 'right')
                :css('float', 'right')
                :css('max-width', maxwidth .. '%')
                :tag('span')
                    :attr('id', 'headernext')
                    :wikitext(args.next)
                    :tag('span')
                        :css('color', '#808080')
                        :wikitext('&nbsp;&nbsp;&#x25BA;')
        end
        if type ~= 'collection' and args.current and args.current ~= '' then
            nav:tag('div')
            	:attr('itemprop', 'name')
                :css('text-align', 'center')
                :css('margin-left', '25%')
                :css('margin-right', '25%')
                :wikitext(args.current)
        end
        footer:tag('div')
            :css('clear', 'both')
    end

    -- Inclusion de l'épigraphe et du sommaire
    if headerType == 'toc' then
        if args.epigraphe and args.epigraphe ~= '' then
            container:wikitext(args.epigraphe)
                :newline()
        end
        container:tag('div')
            :addClass('ws-summary')
            :css('margin-top', '1em')
            :wikitext(args.sammendrag)
    elseif headerType == 'sammendrag' then
        html:wikitext('<div id="ws-summary">') --Bad hack, outputs unbalanced HTML
    end

	--Métadonnées schema.org supplémentaires
	container:tag('link')
        :attr('itemprop', 'url')
        :attr('href', page:fullUrl(nil, 'canonical'))
    container:tag('meta')
        :attr('itemprop', 'inLanguage')
        :attr('content', 'no')  --TODO: que faire pour l'ancien français...
    if args.sted and args.sted ~= '' then
        container:tag('meta')
        :attr('itemprop', 'http://purl.org/library/placeOfPublication')
        :attr('content', args.sted) --TODO: is it the best property URI and the best value format?
    end

    -- Métadonnées, see http://ocoins.info/ for coins.
    local coins = {}
    local uriCoins = 'ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3A'
    coins['rft.genre'] = 'unknown'
    coins['rfr_id'] = tostring( page:fullUrl( nil, "canonical" ) )
    local datahtml = container:tag('div')
        :attr('id', 'ws-data')
        :addClass('ws-noexport')
        :css('display', 'none')
        :css('speak', 'none')
    if args.type then
        datahtml:node( outputMicroformatRow( 'type', args.type ) )
    end
    if args.type and args.type == 'journal' then
        uriCoins = uriCoins .. 'journal'
        if erSammendrag then
            coins['rft.genre'] = 'publication'
            coins['rft.jtitle'] = cleanCoinsParameter( tittel )
        else
            coins['rft.genre'] = 'article'
            coins['rft.atitle'] = cleanCoinsParameter( tittel )
            if args.tittel then
                coins['rft.jtitle'] = cleanCoinsParameter( args.tittel )
                datahtml:node( outputMicroformatRow( 'periodical', cleanCoinsParameter( args.tittel ) ) )
            end
        end
    else
        uriCoins = uriCoins .. 'book'
        if erSammendrag then
            coins['rft.btitle'] = cleanCoinsParameter( tittel )
        else
            coins['rft.atitle'] = cleanCoinsParameter( tittel )
        end
        if args.type and args.type == 'book' then
            if erSammendrag then
                coins['rft.genre'] = 'book'
            else
                coins['rft.genre'] = 'bookitem'
            end
        end
    end
    datahtml:node( outputMicroformatRow( 'title', tittel ) )
    if args.forfatter and args.forfatter ~= '' then
        datahtml:node( outputMicroformatRow( 'author', args.forfatter ) )
        coins['rft.au'] = cleanCoinsParameter( args.forfatter )
    end
    if args.oversetter and args.oversetter ~= '' then
        datahtml:node( outputMicroformatRow( 'translator', args.oversetter ) )
    end
    if args.illustrator and args.illustrator ~= '' then
        datahtml:node( outputMicroformatRow( 'illustrator', args.illustrator ) )
    end
    if args.school and args.school ~= '' then
        datahtml:node( outputMicroformatRow( 'school', args.school ) )
    end
    if args.forlag and args.forlag ~= '' then
        datahtml:node( outputMicroformatRow( 'publisher', args.forlag ) )
        coins['rft.pub'] = cleanCoinsParameter( args.forlag )
    end
    if args.ar and args.ar ~= '' then
        datahtml:node( outputMicroformatRow( 'year', args.ar ) )
        coins['rft.date'] = args.ar
    end
    if args.sted and args.sted ~= '' then
        datahtml:node( outputMicroformatRow( 'place', args.sted ) )
        coins['rft.place'] = args.sted
    end
    if args.fremgang and args.fremgang ~= '' then
        datahtml:node( outputMicroformatRow( 'progress', args.fremgang ) )
    end
    if args.bind and args.bind ~= '' then
        datahtml:node( outputMicroformatRow( 'volume', args.bind ) )
    end
    if args.current and args.current ~= '' then
        datahtml:node( outputMicroformatRow( 'chapter', args.current ) )
    end
    if args.index then
        datahtml:node( outputMicroformatRow( 'scan', args.index ) )
        if args.image and mw.ustring.match(args.image, '^%d+$') ~= nil then
            datahtml:node( outputMicroformatRow( 'cover', args.index .. '/' .. args.image ) )
        end
    end
    if from ~= '' and to ~= '' then
        if from == to then
            datahtml:node( outputMicroformatRow( 'pages', from ) )
        else
            datahtml:node( outputMicroformatRow( 'pages', from .. '-' .. to ) )
        end
        coins['rft.spage'] = from
        coins['rft.epage'] = to
    end
    datahtml:tag('span')
        :addClass('Z3988')
        :attr('title', uriCoins .. '&' .. mw.uri.buildQueryString( coins ))
        :wikitext('&nbsp;')
    
    return html
end

function classement( frame, page, args )
    local classement = require 'Modul:Klassifisering'
    local key = ''
    if args.type and args.type == 'journal' then
        key = classement.getSortKey( {args= {page.text}} )
    elseif args.type and (args.type == 'dictionary' or args.type == 'collection') then
        key = classement.getSortKey( {args= {page.subpageText}} )
    elseif not page.isSubpage then
        key = classement.getSortKey( {args= {page.text}} )
    end
    if key ~= '' then
        --Evite le parse des paramètres passés à la page.
        local child = frame:newChild{ title = page.text, args = {} }
        child:preprocess( '{{DEFAULTSORT:' .. key .. '}}\n' )
    end
end

function pagination( from, to )
    if from ~= '' and to ~= '' then
        if from == to then
            return '<abbr title="side">s.</abbr>&nbsp;' .. formatString(from, 'pageStart' )
        else
            return '<abbr title="sider">s.</abbr>&nbsp;' .. formatString( from, 'pageStart' ) .. '-' .. formatString( to, 'pageEnd' )
        end
    end
end

function outputMicroformatRow( name, value )
    return mw.html.create('span')
        :addClass('ws-' .. name)
        :wikitext(value)
end


local p = {}
 
function p.headerTemplate( frame )
    return headerTemplate( frame )
end
 
return p