Модуль:FtlMarking: различия между версиями
Материал из Space Station 14 Вики
Pok (обсуждение | вклад) мНет описания правки |
Pok (обсуждение | вклад) мНет описания правки |
||
| (не показано 8 промежуточных версий этого же участника) | |||
| Строка 53: | Строка 53: | ||
if attr_str == "" then return nil end | if attr_str == "" then return nil end | ||
local params = {} | local params = {} | ||
local function unquote_val(v) | |||
if not v then return v end | |||
v = trim(v) | |||
v = mw.ustring.gsub(v, "^"(.-)"$", "%1") | |||
v = mw.ustring.gsub(v, '^"(.-)"$', "%1") | |||
return v | |||
end | |||
for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"") do | for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"") do | ||
params[mw.ustring.lower(k)] = v | params[mw.ustring.lower(k)] = unquote_val(v) | ||
end | end | ||
attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"", "") | attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"", "") | ||
for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)") do | for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)") do | ||
params[mw.ustring.lower(k)] = v | params[mw.ustring.lower(k)] = unquote_val(v) | ||
end | end | ||
attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)", "") | attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)", "") | ||
local unnamed = mw.ustring.match(attr_str, "%s*\"(.-)\"") | |||
local unnamed = mw.ustring.match(attr_str, "%s*"(.-)"") or mw.ustring.match(attr_str, "%s*\"(.-)\"") | |||
if unnamed then | if unnamed then | ||
params._value = unnamed | params._value = unquote_val(unnamed) | ||
attr_str = mw.ustring.gsub(attr_str, "%s*"(.-)"", "", 1) | |||
attr_str = mw.ustring.gsub(attr_str, "%s*\"(.-)\"", "", 1) | attr_str = mw.ustring.gsub(attr_str, "%s*\"(.-)\"", "", 1) | ||
end | end | ||
if not params._value then | if not params._value then | ||
local v = mw.ustring.match(attr_str, "%s*([^%s%]]+)") | local v = mw.ustring.match(attr_str, "%s*([^%s%]]+)") | ||
if v then params._value = v end | if v then params._value = unquote_val(v) end | ||
end | end | ||
return params | return params | ||
end | end | ||
| Строка 75: | Строка 89: | ||
local function convert_lists(s) | local function convert_lists(s) | ||
if not s or s == "" then return s end | if not s or s == "" then return s end | ||
local lines = mw.text.split(s, "\n") | |||
local first_non_empty = nil | local first_non_empty = nil | ||
for line in | local first_non_empty_unescaped = nil | ||
for i, line in ipairs(lines) do | |||
if line and line:match("%S") then | if line and line:match("%S") then | ||
first_non_empty = line | first_non_empty = line | ||
first_non_empty_unescaped = mw.ustring.gsub(line, " ", " ") | |||
break | break | ||
end | end | ||
end | end | ||
local enable_numeric = false | local enable_numeric = false | ||
if | if first_non_empty_unescaped and mw.ustring.match(first_non_empty_unescaped, "^%s*%d+%.") then | ||
enable_numeric = true | enable_numeric = true | ||
end | end | ||
local out_lines = {} | local out_lines = {} | ||
for line in | for _, line in ipairs(lines) do | ||
local processed = line | local processed = line | ||
local handled = false | local handled = false | ||
local line_unescaped = mw.ustring.gsub(line, " ", " ") | |||
if enable_numeric then | if enable_numeric then | ||
local leading, num, rest = mw.ustring.match( | local leading, num, rest = mw.ustring.match(line_unescaped, "^(%s*)(%d+)%.%s*(.*)$") | ||
if num then | if num then | ||
local indent = mw.ustring.len(leading or "") | local indent = mw.ustring.len(leading or "") | ||
| Строка 101: | Строка 123: | ||
end | end | ||
end | end | ||
if not handled then | if not handled then | ||
local leading, rest = mw.ustring.match( | local leading, rest = mw.ustring.match(line_unescaped, "^(%s*)%-%s+(.*)$") | ||
if rest then | if rest then | ||
local indent = mw.ustring.len(leading or "") | local indent = mw.ustring.len(leading or "") | ||
| Строка 112: | Строка 135: | ||
end | end | ||
end | end | ||
if not handled then | if not handled then | ||
table.insert(out_lines, processed) | table.insert(out_lines, processed) | ||
end | end | ||
end | end | ||
return table.concat(out_lines, "") | |||
return table.concat(out_lines, "\n") | |||
end | end | ||
| Строка 133: | Строка 158: | ||
visible = mw.ustring.gsub(visible, "|", "|") | visible = mw.ustring.gsub(visible, "|", "|") | ||
tip = mw.ustring.gsub(tip, "|", "|") | tip = mw.ustring.gsub(tip, "|", "|") | ||
return "{{ | return "{{altTooltip|" .. (visible or "") .. "|" .. (tip or "") .. "}}" | ||
end) | end) | ||
while true do | while true do | ||
| Строка 177: | Строка 202: | ||
text = mw.text.unstripNoWiki(text) | text = mw.text.unstripNoWiki(text) | ||
text = process_nowiki_equals(text) | text = process_nowiki_equals(text) | ||
return transform(text) | return frame:preprocess(transform(text)) | ||
end | end | ||
return p | return p | ||
Текущая версия от 11:41, 5 февраля 2026
Для документации этого модуля может быть создана страница Модуль:FtlMarking/doc
local p = {}
local function apply_tag(tag, params, inner)
local t = mw.ustring.lower(tag or "")
if t == "bold" then
return "<b>" .. inner .. "</b>"
elseif t == "italic" then
return "<i>" .. inner .. "</i>"
elseif t == "bolditalic" then
return "<i><b>" .. inner .. "</b></i>"
elseif t == "bullet" then
return "· " .. inner
elseif t == "color" then
local color = params and params._value or ""
return '<span style="color:' .. color .. ';">' .. inner .. '</span>'
elseif t == "head" then
local level = params and tonumber(params._value) or 1
level = math.max(1, math.min(3, level))
local defaultSize = 100
local size = math.ceil(defaultSize * 2 / math.sqrt(level))
return '<span style="font-weight:bold; font-size:' .. size .. '%;">' .. inner .. '</span>'
elseif t == "font" then
local family = params and params._value or nil
local size = params and tonumber(params.size) or nil
local style_parts = {}
if family and family ~= "" then
table.insert(style_parts, "font-family:" .. family)
end
if size and size ~= "" then
table.insert(style_parts, "font-size:" .. size .. "px")
end
if #style_parts == 0 then
return '<span>' .. inner .. '</span>'
else
return '<span style="' .. table.concat(style_parts, "; ") .. ';">' .. inner .. '</span>'
end
else
return inner
end
end
local function trim(s)
if not s then return s end
s = mw.ustring.gsub(s, "^%s+", "")
s = mw.ustring.gsub(s, "%s+$", "")
return s
end
local function parse_attrs(attr_str)
if not attr_str then return nil end
attr_str = mw.ustring.gsub(attr_str, "^%s*=%s*", "")
attr_str = trim(attr_str)
if attr_str == "" then return nil end
local params = {}
local function unquote_val(v)
if not v then return v end
v = trim(v)
v = mw.ustring.gsub(v, "^"(.-)"$", "%1")
v = mw.ustring.gsub(v, '^"(.-)"$', "%1")
return v
end
for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"") do
params[mw.ustring.lower(k)] = unquote_val(v)
end
attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*\"(.-)\"", "")
for k, v in mw.ustring.gmatch(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)") do
params[mw.ustring.lower(k)] = unquote_val(v)
end
attr_str = mw.ustring.gsub(attr_str, "([%w_%-%:]+)%s*=%s*([^%s%]]+)", "")
local unnamed = mw.ustring.match(attr_str, "%s*"(.-)"") or mw.ustring.match(attr_str, "%s*\"(.-)\"")
if unnamed then
params._value = unquote_val(unnamed)
attr_str = mw.ustring.gsub(attr_str, "%s*"(.-)"", "", 1)
attr_str = mw.ustring.gsub(attr_str, "%s*\"(.-)\"", "", 1)
end
if not params._value then
local v = mw.ustring.match(attr_str, "%s*([^%s%]]+)")
if v then params._value = unquote_val(v) end
end
return params
end
local function convert_lists(s)
if not s or s == "" then return s end
local lines = mw.text.split(s, "\n")
local first_non_empty = nil
local first_non_empty_unescaped = nil
for i, line in ipairs(lines) do
if line and line:match("%S") then
first_non_empty = line
first_non_empty_unescaped = mw.ustring.gsub(line, " ", " ")
break
end
end
local enable_numeric = false
if first_non_empty_unescaped and mw.ustring.match(first_non_empty_unescaped, "^%s*%d+%.") then
enable_numeric = true
end
local out_lines = {}
for _, line in ipairs(lines) do
local processed = line
local handled = false
local line_unescaped = mw.ustring.gsub(line, " ", " ")
if enable_numeric then
local leading, num, rest = mw.ustring.match(line_unescaped, "^(%s*)(%d+)%.%s*(.*)$")
if num then
local indent = mw.ustring.len(leading or "")
local level = math.floor(indent / 2)
local hashes = string.rep('#', 1 + level)
processed = hashes .. (rest ~= "" and (" " .. rest) or "")
table.insert(out_lines, processed)
handled = true
end
end
if not handled then
local leading, rest = mw.ustring.match(line_unescaped, "^(%s*)%-%s+(.*)$")
if rest then
local indent = mw.ustring.len(leading or "")
local level = math.floor(indent / 2)
local stars = string.rep('*', 1 + level)
processed = stars .. (rest ~= "" and (" " .. rest) or "")
table.insert(out_lines, processed)
handled = true
end
end
if not handled then
table.insert(out_lines, processed)
end
end
return table.concat(out_lines, "\n")
end
local function transform(s)
s = s or ""
s = mw.ustring.gsub(s, "%[tooltip([^%]]*)%]", function(raw_attrs)
local params = parse_attrs(raw_attrs)
local tip = ""
local visible = ""
if params then
if params.tooltip then tip = params.tooltip end
if params.text then visible = params.text end
if visible == "" and params._value then visible = params._value end
if tip == "" and params._value and visible ~= params._value then tip = params._value end
end
visible = mw.ustring.gsub(visible, "|", "|")
tip = mw.ustring.gsub(tip, "|", "|")
return "{{altTooltip|" .. (visible or "") .. "|" .. (tip or "") .. "}}"
end)
while true do
local c_s, c_e, c_tag = mw.ustring.find(s, "%[/([%w_]+)%]")
if not c_s then break end
local last_o_s, last_o_e = nil, nil
local search_pos = 1
while true do
local a, b = mw.ustring.find(s, "%[" .. c_tag .. "[^%]]*%]", search_pos)
if not a or a > c_s then break end
last_o_s, last_o_e = a, b
search_pos = b + 1
end
if not last_o_s then
s = mw.ustring.sub(s, 1, c_s - 1) .. mw.ustring.sub(s, c_e + 1)
else
local inner = mw.ustring.sub(s, last_o_e + 1, c_s - 1)
local _, _, raw_attrs = mw.ustring.find(s, "%[" .. c_tag .. "([^%]]*)%]", last_o_s)
local params = parse_attrs(raw_attrs)
local replacement = apply_tag(c_tag, params, inner)
s = mw.ustring.sub(s, 1, last_o_s - 1) .. replacement .. mw.ustring.sub(s, c_e + 1)
end
end
s = mw.ustring.gsub(s, "%[/?[%w_]+[^%]]*%]", "")
s = convert_lists(s)
return s
end
local function process_nowiki_equals(str)
str = str:gsub('#', '#')
:gsub('=', '=')
:gsub(' ', ' ')
:gsub('{', '{')
:gsub('"', '"')
:gsub("'", ' ')
:gsub('*', '*')
return str
end
function p.main(frame)
local args = frame.args or {}
local text = args[1] or args.text or ""
text = mw.text.unstripNoWiki(text)
text = process_nowiki_equals(text)
return frame:preprocess(transform(text))
end
return p