La documentation pour ce module peut être créée à Module:Poem/Documentation

-- Permet de construir un poème
--Appel à partir d’une page Wikisource ou d’un module :
-- {{#invoke:Poem|construire|Groupe de lignes|paramètres}}
-- paramètres
-- 1 : Lignes du poème
-- 2 : début, suite, fin
-- 2 : i si tout le poème est sur la même page
-- 3 : i
-- m : marge haut et bas
-- mg: marge de gauche
-- mb: marge du bas
-- lh: line-height
-- fs: taille de la police

local p = {}
local ns
local PSuite = {}
PSuite['ss'] = true
PSuite['sf'] = true
PSuite['suite'] = true
PSuite['s'] = true
PSuite['fin'] = true
PSuite['f'] = true
local PDebut = {}
PDebut['df'] = true
PDebut['ds'] = true
PDebut['i'] = true
PDebut['c'] = true
PDebut['début'] = true
PDebut['d'] = true
local PFin = {}
PFin["df"] = true
PFin["sf"] = true
PFin["fin"] = true
PFin["f"] = true
PFin["i"] = true
PFin["c"] = true
local PBrAvoid = {}
PBrAvoid["strophe"] = true
PBrAvoid["str"] = true

function valUnit(val, unit)
	if tonumber(val) ~= nil then
		val = val .. unit
	end
	return val
end

function br(str)
	if mw.ustring.find( str, 'div') == nil then
		return '<br />'
	else
		return ''
	end
end 

function p.poem( frame )
	local parentFrame = frame:getParent()
    local args = parentFrame.args
	local div
	local str = ""
	--local lettrine = false
	local kn = 0
	local fs = '0'
	
	local mode = args['mode']	
    if not args[1] and frame.args[1] then
		args = frame.args
    end
    titre  = mw.title.getCurrentTitle()
    ns     = titre.nsText
    args[2] = args[2] or 'df'
	args[3] = args[3] or ''
	local indent 
	local dropinitial = false
	if mode == nil then  mode = args['mode'] or '' end
	if mode == '' and args['indent'] then mode = 'indent' end
	if mode == 'normal' then 
		indent = '0'
	else 
		indent = args['indent'] or '6'
	end
	
    if ((PSuite[args[2]] or false) and ns ~= "") or (PDebut[args[2]] or false) then
    	str = str .. '<div style= "display:table; position:relative; margin:0 auto;  '
		if args["mg"] then
			str = str .. "margin-left: " .. valUnit(args["mg"], "em") .. "; "
			if args["m"] then
				 str = str .. "margin-top: " .. args["m"] ..
					"; margin-bottom: " .. args["m"] .. "; "
			end
		else 
			m = args["m"] or "0"
			str = str .. "margin: "  .. m .. " auto; "
		end
		if args[2] == "i" or args[3] == "i" or args[4] == "i" then
			str = str .. "font-style: italic; "
		end
		if args[2] == "c" or args[3] == "c" or args[4] == "c" then
			str = str .. "text-align: center; "
			mode = 'normal'
		end		
		if args["ct"] then
			str = str .. "color: " .. args["ct"] .. "; "
		end
		if args["fs"] then
			str = str .. "font-size: " .. args["fs"] .. "; "
		end
		if args["cf"] then
			str = str .. "background-color: " .. args["cf"] .. "; "
		end
		if args["lh"] then
			str = str .. "line-height: " .. valUnit(args["lh"], "%") .. "; "
		end    	
    	str = str .. '">'
    end
    -- Vérifie si une strophe doit être protégée 
--    if mw.ustring.sub(args[2],1,3) == 'str' or mw.ustring.sub(args[3],1,3) == 'str' then
    if (PBrAvoid[args[2]] or false) or (PBrAvoid[args[3]] or false) then
    	str = str .. '<div style ="page-break-inside:avoid;">'
    end
    -- Retire le premier saut de ligne au début de l’argument
	args[1] = mw.ustring.gsub( args[1], "^\r?\n", "", 1 )
	local lines = mw.text.split(args[1], "\r?\n", false)
	for k,v in pairs(lines) do
		if mw.ustring.match( v, 'dropinitial') ~= nil then
			--v = mw.ustring.match( v, '<span style="display:block;position:absolute.*')
			v = mw.ustring.gsub( v, 'dropinitial" style="', 'dropinitial" style="margin-left: -' .. valUnit(indent, 'em') .. ';"' )
			v = mw.ustring.gsub( v, 'dropinitial%-mid"', 'dropinitial-mid" style= "margin-right: '  .. valUnit(indent, 'em') .. ';')
			fs = (mw.ustring.match( v, '%|(.-)px' ) or '0')
			if fs ~= '0' then
				kn = math.ceil(fs / 23) + k
			else 
				fs = (mw.ustring.match( v, 'dropinitial%-initial.-font%-size: -(.-);' ) or '0')
				kn = nbLignes(fs) + k
			end
			--fs = fs + 10 .. 'px'
		end

		if (mw.ustring.match( v, '{|') ~= nil) then
			accolade = true
			v = '<nowiki/>\n{|'
		end
		if accolade then 
			if (mw.ustring.match( v, '|') ~= nil) then 
				v = '\n' .. v 
			else
				v = '<br />' .. v
			end
			if (mw.ustring.match( v, '|}') ~= nil) then
				accolade = false
				v = v .. '<br />'
			end
		elseif mode == 'normal' then
			v = v  .. br(v)
		elseif mode == "indent" or k < kn then
			dropinitial = false
			ind = valUnit(indent, "em")
			if (mw.ustring.find( v, 'text%-align') == nil) and (mw.ustring.find( v, '<h[r1-9]') == nil) then
				v = '<div style="text-align: left; padding-left: ' .. ind .. '; text-indent: -' .. ind .. ';">' .. v .." </div>"
			else
				v = v  .. br(v)
			end
		else
			if (mw.ustring.find( v, 'text%-align') == nil) and (mw.ustring.find( v, '<h[r1-9]') == nil) then
				v = '<div style="display: inline-block; text-align: left; position:relative; text-align-last: right;  width: auto;">' .. v ..  "</div><br />"
			else
				v = v  .. br(v)
			end
		end
		v = strophe( v )
		str = str .. v
	end
    if (PBrAvoid[args[2]] or false) or (PBrAvoid[args[3]] or false) then
    	str = str .. '</div>'
    end
    if (PFin[args[2]] or ns == "Page") then 
    	str = str .. "</div>"
    end
    --return str
    return frame:preprocess(str)
    --return mw.text.nowiki(frame:preprocess(args[1]))

end

function strophe(str)
	if mw.ustring.find(str, '<span title="beginBR"></span>', 1, true) then
		str = mw.ustring.gsub( str, '<span title="beginBR"></span>', '', 1 )
		str = '<div style ="page-break-inside:avoid;">' .. str
	elseif mw.ustring.find(str, '<span title="endBR"></span>', 1, true) then
		str = mw.ustring.gsub( str, '<span title="endBR"></span>', '', 1 )
		str = str .. '</div>'
	end
	return str	
end

function nbLignes(fs)
	fsN = mw.ustring.match(fs,'(.-)px')
	if fsN ~= nil then return math.ceil(fsN / 23) end
	fsN = mw.ustring.match(fs,'(.-)em')
	if fsN ~= nil then return math.ceil(fsN / 1.6) end
		fsN = mw.ustring.match(fs,'(.-)%%')
	if fsN ~= nil then return math.ceil(fsN / 160) end
	
end

return p