Перайсці да зместу

Модуль:stringconvert

З пляцоўкі Вікіслоўнік

Дакументацыю да гэтага модуля можна стварыць у Модуль:stringconvert/Дакументацыя

local p = {}

local ACUTE     = mw.ustring.char(0x0301)
local MACRON    = mw.ustring.char(0x0304)
local BREVE     = mw.ustring.char(0x0306)
local DIAER     = mw.ustring.char(0x0308)
local macron_tbl = 
{
  ["AA"] = "A", ["aa"] = "a", 
  ["EEE"] = "E", ["eee"] = "e", 
  ["III"] = "I", ["iii"] = "i",
  ["OO"] = "O", ["oo"] = "o",
  ["UUU"] = "U", ["uuu"] = "u",
  ["?"] = "Y", ["?"] = "y", 
  [ACUTE .. MACRON .. BREVE .. DIAER] = ''
}

--[[
strip_macrons

Гэта функцыя выдаляе макроны, знакі націску і замяняе складовыя знакі на звычайныя.

Выкарыстанне:
{{#invoke:stringconvert|strip_macrons|тэкст}}
]]

function p.strip_macrons(str)
	if type(str) == 'table' then -- праверка на глабальнае выкарыстанне
		str = str.args[1]
	end
	for k, v in pairs( macron_tbl ) do
		str = mw.ustring.gsub(str, "[" .. k .. "]", function(c)
			return v
		end)
	end
	return str;
end

--[[
aslink

Гэта функцыя пераўтворыць падзелены коскамі тэкст у падзеленыя коскамі викиссылки.
Сустракаемыя знакі націску захоўваюцца ў тэксце спасылкі, але прыбіраюцца з мэты.

Выкарыстанне:
{{#invoke:stringconvert|aslinks|тэкст|падзельнік}}
ці 
{{#invoke:stringconvert|aslinks|text=тэкст|delimiter=падзельнік|nospace=1|hide=слова|nocomment=1|lang=код мовы}}
]]

function p.aslinks ( frame )
    -- разбор параметраў
    local function getParameters( frame_args, arg_list )
        local new_args = {};
        local index = 1;
        local value;
        for i,arg in ipairs( arg_list ) do
            value = frame_args[arg]
            if value == nil then
                value = frame_args[index];
                index = index + 1;
            end
            new_args[arg] = value;
        end
        return new_args;
    end
    -- вызначэнне булевага значэння ў параметры
    function getBoolean( boolean_str )
        local boolean_value = false;
        if type( boolean_str ) == 'string' then
            boolean_str = boolean_str:lower();
            if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' or boolean_str == '' then
                boolean_value = false;
            else
                boolean_value = true;
            end    
        elseif type( boolean_str ) == 'boolean' then
            boolean_value = boolean_str;
        end    
        return boolean_value
    end
    
    local new_args = getParameters( frame.args, {'text', 'delimiter', 'nospace', 'hide', 'nocomment', 'lang' } );
    local hide_word = new_args['hide'] or '';
    local text = new_args['text'] or '';
    local delimiter = new_args['delimiter'];
    if delimiter == nil or delimiter == '' then
        delimiter = ',';
    else
        delimiter = mw.text.decode(delimiter);
    end
    local nospace = getBoolean( new_args['nospace']);
    if not nospace then
        -- дадаваны прабел і непарыўны прабел
        delimiter = delimiter .. ' ' .. mw.ustring.char(160);
    end
	local nocomment = getBoolean( new_args['nocomment']);
	if  nocomment then
		delimiter = delimiter .. '%(%)';
	end
	local lang= new_args['lang'];
	local langlink = '';
	if lang then
		local trimmed = mw.text.trim(lang);
		if trimmed == 'ru' then
			langlink = "#Рускі"	
		else
			local languages = mw.loadData("Module:languages/data");
			local l = languages[trimmed];
			if l and l[2] then
				langlink = '#' ..	l[2];
			end
		end
	end
	-- падзел радка 
    local function mygsplit(str, pattern) 
        local l = mw.ustring.len( str );
        return function (state, s)
            if s <= l then
                local e, n = mw.ustring.find( str, pattern, s, false );
                local ret;
                local sep = '';
                if not e then
                    ret = mw.ustring.sub( str, s );
                    s = l + 1
                elseif n < e then
                    ret = mw.ustring.sub( str, s, e );
                    if e < l then
                        s = e + 1;
                    else
                        s = l + 1;
                    end
                else
                    ret = e > s and mw.ustring.sub( str, s, e - 1 ) or '';
                    sep = mw.ustring.sub( str, e, n );
                    s = n + 1
                end
                return s, ret, sep
            else
                s = nil;
                return s, ret, sep
            end
        end, nil, 1 -- iterator, state, initial value
    end    
    -- пошук тэгаў з улікам укладзенасці
    local function findtag( str, s )
        local ct = 1;
        local start_pos = 1;
        local start_tag = '';
        while true do
            local e, n, close_tag, tag_name, single_tag  = mw.ustring.find( str, "<(/?)([A-Za-z]+).-(/?)>", s, false );
            if not e then
                return nil, -1
            else 
                if single_tag ~= '' then 
                    if start_tag == '' then
                        return e, n; -- знойдзены адзінкавы няпарны тэг
                    else 
                        s = n + 1; -- прапусканы ўкладзены непартный тэг
                    end
                elseif close_tag ~= '' then
                    if start_tag == '' then
                        return e, n; -- знойдзены адзінкавы які зачыняе тэг
                    elseif tag_name == start_tag then
                        ct = ct - 1;
                        if ct == 1 then
                            return  start_pos, n; -- знойдзены што зачыняе тэг
                        else
                            s = n + 1; -- знойдзены ўкладзены які зачыняе тэг
                        end
                    else
                        s = n + 1; -- прапусканы ўкладзены што зачыняе тэг
                    end
                else
                    if start_tag == '' then
                        start_tag = tag_name;
                        start_pos = e;
                        ct = ct + 1;
                        s = n + 1; -- знойдзены першы адкрывалы тэг
                    elseif tag_name == start_tag then
                        ct = ct + 1;
                        s = n + 1; -- знойдзены ўкладзены адкрывалы тэг з тым жа імем
                    else
                        s = n + 1; -- прапусканы ўкладзены адкрывалы тэг
                    end
                end
            end
        end
    end
    -- падзел тэгаў
    local function tsplit(str) 
        local l = mw.ustring.len( str );
        return function (state, s)
            if s <= l then
                local e, n = findtag( str, s );
                local ret;
                local sep = '';
                if not e then
                    ret = mw.ustring.sub( str, s );
                    s = l + 1
                elseif n < e then
                    ret = mw.ustring.sub( str, s, e );
                    if e < l then
                        s = e + 1;
                    else
                        s = l + 1;
                    end
                else
                    ret = e > s and mw.ustring.sub( str, s, e - 1 ) or '';
                    sep = mw.ustring.sub( str, e, n );
                    s = n + 1
                end
                return s, ret, sep
            else
                s = nil;
                return s, ret, sep
            end
        end, nil, 1 -- iterator, state, initial value
    end  
    -- падзел пакінутага тэксту
    local function myparser(text, level)
        if text ~= '' then
            if mw.ustring.find(text, '[|&]', 1, false) ~= nil or -- не апрацоўваем тэкст, які змяшчае пайп і апмерсант
               mw.ustring.find(text, '^[%p%d]+$', 1, false) ~= nil then  -- і адзінкавыя знакі пунктуацыі і лічбы
               return text; 
            else
                local before, str, after = mw.ustring.match(text, "^(%s*)(.-)(%s*)$", 1);
                if before ~= nil and str ~= nil and str ~= '' then
                	local link = str;
                	if lang == "la" then
                    	link = p.strip_macrons(str) -- прыбіраны дыякрытычныя знакі
                    else
                    	link =  mw.ustring.gsub(str, ACUTE, '') -- прыбіраны толькі знак націску
                    end
                    if str ~= link or langlink ~= ''  then
                        str = link .. langlink .. '|'.. str;
                    end
                    text = before .. "[[" .. str .. "]]" .. after;
                end
            end
        end
        return text; 
    end
    local handlers = {};
    -- падзел тэксту па шаблоне
    local function parse(text, level)
        local result = "";
        local pattern = handlers[level][1];
        local parser = handlers[level][2];
        for i, str, sep in mygsplit(text, pattern, false ) do
            if str ~= "" then
                result = result .. parser(str, level+1);
            end
            if sep ~= "" then
                result = result .. sep;
            end
        end
        if result == "" then
            return text;
        else
            return result;
        end
    end
    local stripers = {};
    local striped = {};
    local stripid = 0;
    local k = 1;
    -- замена тэксту з захаваннем
    local function striptext(text)
        stripid = stripid +1;
        local key = '<' .. stripid .. '>';
        striped[key] = text;
        return key;
    end
    -- выразанне тэксту па шаблоне
    local function strip(text)
        for j, pattern in ipairs(stripers) do
            local result = "";
            for i, str, sep in mygsplit(text, pattern, false ) do
                if str ~= "" then
                    result = result .. str;
                end
                if sep ~= "" then
                    result = result .. striptext(sep);
                end
            end
            if result ~= '' then
                text = result; -- тэкст для наступнага апрацоўніка
            end;
        end
        return text;
    end
    -- аднаўленне выразанага тэксту па шаблоне
    local function unstrip(text)
        local result = '';
        for i, str, sep in mygsplit(text, "<%d->", false ) do
            if str ~= "" then
                result = result .. str;
            end
            if sep ~= "" then
                result = result .. unstrip(striped[sep]);
            end
        end
        return result;
    end
    -- выразанне тэгаў
    local function striptags(text)
        local result = "";
        for i, str, sep in tsplit(text) do
            if str ~= "" then
                result = result .. str;
            end
            if sep ~= "" then
                result = result .. striptext(sep);
            end
        end
        if result == '' then
            return text;
        else
            return result;
        end
    end
    -- зваротная совестымост з шаблонам lang, куды часам перадаецца тэкст сраздэленный шаблонам {{!}}
    text = mw.ustring.gsub(text, '^%s*([^%[|,;]+|[^%]|,;]+)%s*$', '[[%1]]'); 

    text = striptags(text); -- выразаны HTML тэгі
    stripers = {}
    table.insert(stripers, "{|.*|}");         -- выключаны табліцы
    if not nocomment then
    	table.insert(stripers, "%b()");       -- выключаны тэкст у круглых дужках
    end
    table.insert(stripers, "%[%[.-%]%]%S*");  -- выключаны ўнутраныя спасылкі
    table.insert(stripers, "%b[]");           -- выключаны вонкавыя спасылкі
    table.insert(stripers, "'''[^']-'''");    -- выключаны тэкст у патройных адзінарных двукоссях
    table.insert(stripers, "''[^']-''");      -- выключаны тэкст у падвойных адзінарных двукоссях
    text = strip(text);     -- выразаны па шаблоне
    local l = 1;
    handlers[l] = { "\r?\n",                 parse }; l=l+1; -- выключаны падзельнікі радкоў
    handlers[l] = { "%b<>",                  parse }; l=l+1; -- выключаны тэкст у кутніх дужках
    handlers[l] = { "%s*[" .. delimiter .."]+%s*", myparser };     -- падзяляны пакінутае
    text = parse(text, 1);  -- апрацоўваем
    if stripid ~= 0 then
        text = unstrip(text); -- аднаўляем выразанае
    end;
    if hide_word ~= '' then
    	local cnt = 0;
    	-- выдаленне спасылкі на слова
    	hide_word = mw.ustring.gsub( hide_word, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ); -- які маскіруецца спецзнакі
    	text, cnt = mw.ustring.gsub( text, '%[%[' .. hide_word ..'%|[^%]]*%]%]%w* *,? *', '' ); 
    	if cnt == 0 then
    		text, cnt = mw.ustring.gsub( text, '%[%[' .. hide_word ..'%]%]%w* *,? *', '' ); 
    	end
    	if cnt ~= 0 then
    		text = mw.ustring.gsub( text, '^%p+$', '' ); -- выдаляны радок якая складаецца толькі з падзяляльных знакаў
    		text = mw.ustring.gsub( text, '[,;] *;', ';' ); -- выдаляны коску перад кропкай з коскі
    		text = mw.ustring.gsub( text, ', *$', '' ); -- выдаляны коску ў канцы радка
    		text = mw.ustring.gsub( text, '^[;,] *', '' ); -- выдаляны коску ці кропку з коскі напачатку радкі
		end
    end
    return text;
end

return p