Hopp til innhold

Modul:Smartbox/parsers

Fra Wikipedia, den frie encyklopedi
Moduldokumentasjon


--- The local language
local contentLanguage = mw.getContentLanguage()

local mt = {}

local Units = nil

--- Replace terms with preformatted strings
local function replaceTerms( str, units )
	if not units then
		return str
	end

	local tmp,_ = string.gsub( str, '(%S+)', function( part ) return units[part] or part end)

	return tmp
end

local Parsers = {
	--- The parsers for number type
	['number'] = {

		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-number', { nil }
			end
		},

		-- single number
		{
			'^%s*[-+,.%d]+%s*$', 
			function( str, params )
				local num = contentLanguage:parseFormattedNumber( mw.text.trim( str ) )
				if not num then
					return 'failed-number', { nil }
				end
				local formatted = params.format and mw.ustring.format( params.format, num ) or nil
				return 'single-number',
					{
						formatted or mw.message.numParam( num )
					}
			end
		},

		-- number with a prefix
		{
			'^%s*%D+[-+,.%d]+%s*$', 
			function( str, params )
				local prefix, value = str:match( '^(%s*%D+)([-+,.%d]+%s*)$' )
				local num = contentLanguage:parseFormattedNumber( mw.text.trim( value ) )
				if not num then
					return 'failed-number', { nil }
				end
				local formatted = params.format and mw.ustring.format( params.format, num ) or nil
				local prefixed = mw.text.trim( prefix )
				return 'prefix-number',
					{
						Units and replaceTerms( mw.text.nowiki( prefixed ), Units ) or prefixed,
						formatted or mw.message.numParam( num )
					}
			end
		},

		-- number with a suffix
		{
			'^%s*[-+,.%d]+%D-%s*$', -- this can hit a string with only trailing blanks
			function( str, params )
				local value, suffix = str:match( '^(%s*[-+,.%d]+)(%D-%s*)$' )
				local num = contentLanguage:parseFormattedNumber( mw.text.trim( value ) )
				if not num then
					return 'failed-number', { nil }
				end
				local formatted = params.format and mw.ustring.format( params.format, num ) or nil
				local suffixed = mw.text.trim( suffix )
				return 'suffix-number',
					{
						formatted or mw.message.numParam( num ),
						Units and replaceTerms( mw.text.nowiki( suffixed ), Units ) or suffixed,
					}
			end
		},

		-- number with circumfix
		{
			'^%s*%D+[-+,.%d]+%D-%s*$', 
			function( str, params )
				local prefix, value, suffix = str:match( '^(%s*%D+)([-+,.%d]+)(%D-%s*)$' )
				local num = contentLanguage:parseFormattedNumber( mw.text.trim( value ) )
				if not num then
					return 'failed-number', { nil }
				end
				local formatted = params.format and mw.ustring.format( params.format, num ) or nil
				local prefixed = mw.text.trim( prefix )
				local suffixed = mw.text.trim( suffix )
				return 'circumfix-number',
					{
						Units and replaceTerms( mw.text.nowiki( prefixed ), Units ) or prefixed,
						formatted or mw.message.numParam( num ),
						Units and replaceTerms( mw.text.nowiki( suffixed ), Units ) or suffixed,
					}
			end
		},

		-- catch all
		{
			'^.*$', 
			function( str, params )
				return 'failed-number', { nil }
			end
		}
	},

	--- The parsers for string type
	['string'] = {

		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-string', { nil }
			end
		},

		-- single value
		{
			'^%s*%S.*$', 
			function( str, params )
				local text = mw.text.trim( str )
				return 'single-string', { mw.text.nowiki( text ) }
			end
		}
	},

	--- The parsers for unknown type
	['unknown'] = {

		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-unknown', { nil }
			end
		},

		-- single value
		{
			'^%s*%S.*$', 
			function( str, params )
				local text = mw.text.trim( str )
				-- As 'unknown' this should be escaped per def.
				return 'single-unknown', { mw.text.nowiki( text ) }
			end
		}
	},

	--- The parsers for content type
	['content'] = {

		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-content', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*$', 
			function( str, params )
				local text = mw.text.trim( str )
				return 'single-content', { text }
			end
		}
	},

	--- The parsers for line type
	['line'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-line', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*$', 
			function( str, params )
				local text = mw.text.trim( str )
				return 'single-line', { text }
			end
		}
	},

	--- The parsers for boolean type
	['boolean'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-boolean', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%d%s*$', 
			function( str, params )
				local num = tonumber( mw.text.trim( str ) )
				if not num then
					return 'failed-boolean', { nil }
				end
				return 'single-boolean', { mw.message.numParam( num ) }
			end
		},
		
		-- catch all
		{
			'^.*$', 
			function( str, params )
				return 'failed-boolean', { nil }
			end
		}
	},

	--- The parsers for wiki-user-name type
	['wiki-user-name'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-wiki-user-name', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*%s*$', 
			function( str, params )
				local text = mw.text.trim( str )
				local title = mw.title.new( text, 'user' )
				if not title then
					return 'failed-wiki-user-name', { nil }
				end
				if not title:inNamespace( 'user' ) then
					return 'failed-wiki-user-name', { nil }
				end
				if title.isSubpage then
					return 'failed-wiki-user-name', { nil }
				end
				return 'single-wiki-user-name', { text }
			end
		}
	},

	--- The parsers for wiki-page-name type
	['wiki-page-name'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-wiki-page-name', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*%s*$', 
			function( str, params )
				local text = mw.text.trim( str )
				local title = mw.title.new( text )
				if not title then
					return 'failed-wiki-page-name', { nil }
				end
				return 'single-wiki-page-name', { text }
			end
		}
	},

	--- The parsers for wiki-file-name type
	['wiki-file-name'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-wiki-file-name', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*%s*$', 
			function( str, params )
				local text = mw.text.trim( str )
				local title = mw.title.new( text, 'file' )
				if not title then
					return 'failed-wiki-file-name', { nil }
				end
				if not title:inNamespace( 'file' ) then
					return 'failed-wiki-file-name', { nil }
				end
				if title.isSubpage then
					return 'failed-wiki-file-name', { nil }
				end
				return 'single-wiki-file-name', { text }
			end
		}
	},

	--- The parsers for wiki-template-name type
	['wiki-template-name'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-wiki-template-name', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*%s*$', 
			function( str, params )
				local text = mw.text.trim( str )
				local title = mw.title.new( text, 'template' )
				if not title then
					return 'failed-wiki-template-name', { nil }
				end
				if not title:inNamespace( 'template' ) then
					return 'failed-wiki-template-name', { nil }
				end
				return 'single-wiki-template-name', { text }
			end
		}
	},

	--- The parsers for url type
	['url'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-url', { nil }
			end
		},
		
		-- single type
		{
			'^%s*%S.*$', 
			function( str, params )
				local text = mw.text.trim( str )
				local uri = mw.uri.new( text )
				if not uri then
					return 'failed-url', { nil }
				end
				local valid = mw.uri.validate( uri )
				if valid ~= true then
					return 'failed-url', { nil }
				end
				return 'single-url', { text }
			end
		}
	},

	--- The parsers for date type
	['date'] = {
		
		-- empty value
		{
			'^%s*$', 
			function( str, params )
				return 'empty-date', { nil }
			end
		},
		
		-- single value
		{
			'^%s*%S.*%s*$', 
			function( str, params )
				local date = contentLanguage:formatDate( params.format or 'Y-m-d"T"H:i:s', mw.text.trim( str ) )
				if not date then
					return 'failed-date', { nil }
				end
				return 'single-date', { date }
			end
		}
	}
}

Parsers = setmetatable( Parsers, mt )

function mt.__call( tbl, units )
	Units = units
	return tbl
end

-- This little snippet will make itpossible to interactively
-- test the functions from the test console
local title = mw.title.getCurrentTitle()
if title:inNamespaces( 828, 829) then -- module and module discussion
	mt._replaceTerms = replaceTerms
end

return Parsers