Module:Header template

La bibliothèque libre.
Sauter à la navigation Sauter à la recherche
Documentation du module Documentation du module[voir] [modifier] [purger]
La documentation de ce module est incluse depuis sa sous-page de documentation.
Voir Aide:Transclusion pour l’utilisation de la commande <pages index=… />.
  • Modèle utilisé par la balise <pages/> pour générer les boîtes titres
  • Les paramètres acceptés par ce modèle proviennent de la page d’index.
  • Les paramètres peuvent aussi être passés à la commande "pages".
  • Exemple :
 <pages index=foo header=1 auteur="[[Balzac]]" />
Détails techniques

Ce modèle est implémenté en Lua via le module Header Template. Il utilise les paramètres suivants définis par l’extension ProofreadPage :

paramètre description
from la valeur from définie par l’utilisateur, 1 par défaut
displayed_from le numéro de page à afficher pour la première page (par défaut celui défini dans la page Livre:)
to la valeur to définie par l’utilisateur, par défaut la dernière page
displayed_to le numéro de page à afficher pour la dernière page (par défaut celui défini dans la page Livre:)
current le nom du lien pointant vers la page courante dans le sommaire de la page d’index du Livre
prev le nom du lien pointant vers la page précédant la page courante dans le sommaire de la page d’index du Livre
next le nom du lien pointant vers la page suivant la page courante dans le sommaire de la page d’index du Livre
value la valeur de l’attribut header de la balise <pages />, ou toc si ni from ni to ne sont précisés

Les autres paramètres sont les noms des champs apparaissant dans le formulaire de l’index du Livre. Leur valeur est celle qui apparaît dans le formulaire, sauf si l’utilisateur l'a redéfinie dans la balise <pages />, auquel cas, la valeur de la balise a priorité sur celle de l’index.

Pour le paramètre type, la valeur apparaissant dans le menu déroulant du formulaire de la page d’index est convertie en un nom à usage interne suivant le tableau de correspondance suivant :

valeur interne valeur du menu déroulant
book Livre
collection Recueil
journal Journal ou revue
phdthesis Thèse, rapport
dictionary Dictionnaire, encyclopédie, ouvrage de référence

C’est la valeur interne qui est utilisée par le modèle. De même, si l’utilisateur souhaite redéfinir la valeur du champ type à l’intérieur de la balise <pages />, il doit utiliser la valeur interne.

function errorMessage(text)
	-- Return a html formated version of text stylized as an error.
	local html = mw.html.create('div')
	html:addClass('error')
		:wikitext(text)
		:wikitext('[[Catégorie:Pages faisant un appel erroné au modèle Auteur]]')
	return tostring(html)
end

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


function toAbsoluteTitle( relative_title, base_title )
	 --TODO: hacky implementation
	return mw.getCurrentFrame():callParserFunction( '#rel2abs', { relative_title, tostring( base_title or mw.title.getCurrentTitle() ) } )
end

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

function formatYear( date, schema_property )
    local 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/Thing') --TODO: better types
        :tag('span')
            :attr('itemprop', 'name')
            :wikitext(name)
            :done()
    )
end


function formatLink( page, label, schema_property )
    local title = mw.title.new( toAbsoluteTitle( page ) )
    if title == nil then
    	return tostring(mw.html.create('span')
        	:attr('itemprop', schema_property)
        	:attr('itemscope', '')
        	:attr('itemtype', 'http://schema.org/Thing') --TODO: better types
        	:wikitext('[[' .. page .. '|<span itemprop="name">' .. label .. '</span>]]')
    	)
    end
    if title.isRedirect then
        title = title.redirectTarget
    end
    local tag = mw.html.create('span')
        :attr('itemprop', schema_property)
        :attr('itemscope', '')
        :attr('itemtype', 'http://schema.org/Thing') --TODO: better types
        :wikitext('[[' .. title.fullText .. '|<span itemprop="name">' .. label .. '</span>]]')
        :tag('link')
            :attr('itemprop', 'mainEntityOfPage')
            :attr('href', title:fullUrl(nil, 'canonical'))
            :done()
    local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
    if itemId ~= nil then
    	tag:attr('itemid', 'http://www.wikidata.org/entity/' .. itemId)
    end
    return tostring(tag)
end


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


function formatTitleLink( page, label, schema_property )
    local title = mw.title.new( toAbsoluteTitle( page ) )
    if title == nil then
    	return '[[' .. page .. '|' .. label .. ']]'
    end
    if title.isRedirect then
        title = title.redirectTarget
    end
    local tag = 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', 'mainEntityOfPage')
            :attr('href', title:fullUrl(nil, 'canonical'))
            :done()
    local itemId = mw.wikibase.getEntityIdForTitle(title.fullText)
    if itemId ~= nil then
    	tag:attr('itemid', 'http://www.wikidata.org/entity/' .. itemId)
    end
    return tostring(tag)
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 estSommaire = (headerType == 'sommaire' 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 estSommaire then
                schema_type = 'http://schema.org/Book'
            else
                schema_type = 'http://schema.org/Chapter'
            end
        elseif args.type == 'collection' then
            if estSommaire then
            	schema_type = 'https://schema.org/Collection'
            end
        elseif args.type == 'journal' then
            if estSommaire then
            	schema_type = 'https://schema.org/PublicationVolume'
            else
                schema_type = 'http://schema.org/Article'
            end
        elseif args.type == 'phdthesis' then
            if estSommaire 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.sommaire then
            container:tag( 'div' )
                :addClass('ws-summary')
                :css('margin-top', '1em')
                :newline()
                :wikitext(args.sommaire)
        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

    --Auteur
    if args.auteur and args.auteur ~= '' then
        headertemplate:tag('div')
            :addClass('headertemplate-author')
            :wikitext(parseLinkWikitext(args.auteur, 'author'))
    end

    --Titre
    local titre = formatString( page.baseText, 'name' )
    if args.type == 'collection' then
        if args.recueil and args.recueil ~= '' 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.
            -- titre = titre .. '&#32;— <i>' .. args.recueil .. '</i>'
             titre = '<i>' .. parseTitleWikitext(args.recueil, 'isPartOf') .. '</i>'
        elseif args.current then
            titre = formatString( args.current, 'name' )
        else
        	if estSommaire then
        		titre = formatString( titre, 'name' )
    		else
    			titre = parseTitleWikitext(titre, 'isPartOf')
	    	end
	    end

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

    --References
    local references = headertemplate:tag('div')
        :addClass('headertemplate-reference')
    if args.traducteur and args.traducteur ~= '' then
        references:wikitext('Traduction par ' .. parseLinkWikitext(args.traducteur, 'translator') .. '.')
            :tag('br')
    end
    if estSommaire and args.illustrateur and args.illustrateur ~= '' then
        references:wikitext('Illustrations par ' .. parseLinkWikitext(args.illustrateur, 'illustrator') .. '.')
            :tag('br')
    end

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

    local infos = {} --Liste des données à afficher séparés par une virgule
    if args.type == 'collection' then
        if args.titre and args.titre ~= '' then
            table.insert( infos, '<i>' .. parseTitleWikitext(args.titre, 'isPartOf') .. '</i>' )
        end
        if args.editeur_scientifique and args.editeur_scientifique ~= '' then
            table.insert( infos, 'Texte établi par ' .. parseLinkWikitext( args.editeur_scientifique, 'editor' ) )
        end
        if args.editeur and args.editeur ~= '' then
            table.insert( infos, formatPublisherWithName( args.editeur ) )
        end
        if args.annee and args.annee ~= '' then
            table.insert( infos, formatYear( args.annee, 'datePublished' ) )
        end
        if not estSommaire then
            if args.volume and args.volume ~= '' then
                table.insert( infos, formatString( args.volume, 'volumeNumber' ) )
            end
        end
    elseif args.type == 'journal' then
        if not estSommaire then
            table.insert( infos, '<i>' .. parseTitleWikitext( args.titre, 'isPartOf' ) .. '</i>' )
            if args.volume and args.volume ~= '' then
                table.insert( infos, formatString( args.volume, 'volumeNumber' ) )
            end
        end
        if args.annee and args.annee ~= '' then
            table.insert( infos, formatYear( args.annee, 'datePublished' ) )
        end
    else
        if args.editeur_scientifique and args.editeur_scientifique ~= '' then
            table.insert( infos, 'Texte établi par ' .. parseLinkWikitext( args.editeur_scientifique, 'editor' ) )
        end
        if args.editeur and args.editeur ~= '' then
            table.insert( infos, formatPublisherWithName( args.editeur ) )
        end
        if args.annee and args.annee ~= '' then
            table.insert( infos, formatYear( args.annee, 'datePublished' ) )
        end
    end
    local line = ''
    if infos ~= {} then
        line = table.concat( infos, ',&nbsp;' )
    end

    --Parenthèse
    if not estSommaire and from ~= '' then
        local temp = ''
        if args.volume and args.volume ~= '' and args.type ~= 'collection' and args.type ~= 'journal' then
            temp = formatString( args.volume, '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 estSommaire 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 estSommaire 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.type ~= 'collection' and 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(parseLinkWikitext(args.prev, 'previousItem'))
        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(parseLinkWikitext(args.next, 'nextItem'))
                    :tag('span')
                        :css('color', '#808080')
                        :wikitext('&nbsp;&nbsp;&#x25BA;')
        end
        if args.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
    
    
    -- Catégories
    if estSommaire and (not item or not item['claims'] or not item['claims']['P629']) then
	    container:wikitext('[[Catégorie:Éditions sans œuvre liée]]')
	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.sommaire)
    elseif headerType == 'sommaire' 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', 'mainEntityOfPage')
        :attr('href', page:fullUrl(nil, 'canonical'))
    container:tag('meta')
        :attr('itemprop', 'inLanguage')
        :attr('content', 'fr')  --TODO: que faire pour l'ancien français...
    if args.lieu and args.lieu ~= '' then
        container:tag('meta')
        :attr('itemprop', 'http://purl.org/library/placeOfPublication')
        :attr('content', args.lieu) --TODO: is it the best property URI and the best value format?
    end
    if args.index and args.index ~= '' then
    	local indexFile = mw.title.makeTitle('File', args.index)
    	if indexFile ~= nil and indexFile.file.exists then
    		container:tag('span')
        		:attr('itemprop', 'associatedMedia')
    			:attr('itemscope', '')
    			:attr('itemtype', 'http://schema.org/MediaObject')
        		:tag('link')
        			:attr('itemprop', 'mainEntityOfPage')
    				:attr('href', indexFile:fullUrl(nil, 'canonical'))
    				:done()
    			:tag('meta')
        			:attr('itemprop', 'width')
    				:attr('content', indexFile.file.width)
    				:done()
    			:tag('meta')
        			:attr('itemprop', 'height')
    				:attr('content', indexFile.file.height)
    				:done()
    			:tag('meta')
        			:attr('itemprop', 'fileFormat')
    				:attr('content', indexFile.file.mimeType)
    				:done()
    	end
    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 estSommaire then
            coins['rft.genre'] = 'publication'
            coins['rft.jtitle'] = cleanCoinsParameter( titre )
        else
            coins['rft.genre'] = 'article'
            coins['rft.atitle'] = cleanCoinsParameter( titre )
            if args.titre then
                coins['rft.jtitle'] = cleanCoinsParameter( args.titre )
                datahtml:node( outputMicroformatRow( 'periodical', cleanCoinsParameter( args.titre ) ) )
            end
        end
    else
        uriCoins = uriCoins .. 'book'
        if estSommaire then
            coins['rft.btitle'] = cleanCoinsParameter( titre )
        else
            coins['rft.atitle'] = cleanCoinsParameter( titre )
        end
        if args.type and args.type == 'book' then
            if estSommaire then
                coins['rft.genre'] = 'book'
            else
                coins['rft.genre'] = 'bookitem'
            end
        end
    end
    datahtml:node( outputMicroformatRow( 'title', titre ) )
    if args.auteur and args.auteur ~= '' then
        datahtml:node( outputMicroformatRow( 'author', args.auteur ) )
        coins['rft.au'] = cleanCoinsParameter( args.auteur )
    end
    if args.traducteur and args.traducteur ~= '' then
        datahtml:node( outputMicroformatRow( 'translator', args.traducteur ) )
    end
    if args.illustrateur and args.illustrateur ~= '' then
        datahtml:node( outputMicroformatRow( 'illustrator', args.illustrateur ) )
    end
    if args.school and args.school ~= '' then
        datahtml:node( outputMicroformatRow( 'school', args.school ) )
    end
    if args.editeur and args.editeur ~= '' then
        datahtml:node( outputMicroformatRow( 'publisher', args.editeur ) )
        coins['rft.pub'] = cleanCoinsParameter( args.editeur )
    end
    if args.annee and args.annee ~= '' then
        datahtml:node( outputMicroformatRow( 'year', args.annee ) )
        coins['rft.date'] = args.annee
    end
    if args.lieu and args.lieu ~= '' then
        datahtml:node( outputMicroformatRow( 'place', args.lieu ) )
        coins['rft.place'] = args.lieu
    end
    if args.avancement and args.avancement ~= '' then
        datahtml:node( outputMicroformatRow( 'progress', args.avancement ) )
    end
    if args.volume and args.volume ~= '' then
        datahtml:node( outputMicroformatRow( 'volume', args.volume ) )
    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 'Module:Classement'
    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="page">p.</abbr>&nbsp;' .. formatString( from, 'pagination' )
        else
            return '<abbr title="pages">p.</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

function p.voirEditions( frame )
	local args = frame:getParent().args
	if not args[1] or args[1] == '' then
		return errorMessage("Le modèle VoirEdition prend en paramètre un lien vers la liste des éditions")
	end

	local node = mw.html.create('small')
		:addClass('ws-noexport')
		:css({
			['text-align'] = 'center',
			['font-style'] =  'italic'
		})
		:attr('itemscope', '')
		:attr('itemtype', 'http://schema.org/CreativeWork')

	local itemId = mw.wikibase.getEntityIdForCurrentPage()
	if itemId ~= nil then
		node:attr('itemid', 'http://www.wikidata.org/entity/' .. itemId)
	end

	node:wikitext('[[Image:List2.svg|25px|lien=]] Pour les autres éditions de ce texte, voir ')
		:wikitext(parseTitleWikitext(args[1], 'exampleOfWork'))
		:wikitext('.')

	return tostring(node)
end
 
return p