This module helps to automatically build elegant description of data-modules for Module:uz-inflection.
I.e.: Module:uz-inflection/data/uz-noun
If you will find any mistakes or misprints in English please fill free to fix them here: Module:uz-inflection-docs/i18n/en
-- Uz-inflection-docs v0.9.5
-- 2015-07-10
-- This parameter `lang` should be changed when move source code to another wiktionary
-- It is used to get translations from corresponding i18n-module
local lang = 'en'
local export = {}
local u = require("Module:uz-utils")
local wu = require("Module:uz-wiki-utils")
local du = require("Module:uz-inflection-docs-utils")
local i18n = mw.loadData("Module:uz-inflection-docs/i18n/" .. lang)
local data
-- TODO: move this function to uz-inflection-docs-utils
local function classes_order(t, key_1, key_2)
if key_1 == nil then
return true
elseif key_2 == nil then
return false
end
local order_class_names = du.get_ordered_classes(du.conditions)
local key_1_index = 999
local key_2_index = 999
for i, order_class_name in pairs(order_class_names) do
if key_1:match('^' .. order_class_name) then
key_1_index = i
end
if key_2:match('^' .. order_class_name) then
key_2_index = i
end
end
if key_1_index ~= key_2_index then
return key_1_index < key_2_index
end
return key_1 < key_2
end
-- Function to load corresponding data-module
local function load_data(frame)
local data_name = frame.args
if data_name == '' then
return 'Error in module ]: Name of data-module is absent.'
end
return mw.loadData("Module:uz-inflection/data/" .. data_name);
end
-- Section "Template"
local function print_template_name()
local r = string.format('=== %s ===\n', i18n.TEMPLATE_HEADER)
r = r .. string.format('{{%s|%s}}\n\n', i18n.TEMPLATE_TEMPLATE, data)
return r
end
-- Section "Affixes in 'affixes'"
local function print_affixes()
local r = ''
r = r .. string.format("=== %s '''<code>affixes</code>''' %s ===\n", i18n.SECTION, i18n.AFFIXES_HEADER_DESC)
r = r .. '{| ' .. wu.table_class() .. '\n'
r = r .. string.format('! %s || %s || %s \n', i18n.NAME, i18n.VALUE, i18n.CHANGES)
r = r .. '|-\n'
for affix_key, affix_value in u.spairs(du.affixes, du.case_order) do
changes = du.print_changes(du.affixes_changes, affix_key, wu.span_blue)
_anchor = wu.anchor('var', affix_key) .. ' '
r = r .. '| ' .. du.var(affix_key) .. '\n'
r = r .. '| align=center | '
if changes == '' then -- we need this because if column 'Changes' is empty then anchor on empty cell is working in a wrong way.
r = r .. _anchor
end
r = r .. '"' .. wu.span_blue(affix_value) .. '"\n'
r = r .. '|| '
if changes then -- if column 'Changes' is not empty then anchor should be on it.
r = r .. _anchor
end
r = r .. changes .. '\n'
r = r .. '|-\n'
end
r = r .. '|}\n\n'
return r
end
local function print_arguments()
local r = ''
r = r .. string.format('==== %s ====\n', i18n.ARGUMENTS_HEADER)
r = r .. '{| ' .. wu.table_class() .. '\n'
r = r .. string.format('! %s || %s \n', i18n.NAME, i18n.POSSIBLE_VALUES)
r = r .. '|-\n'
for key, value in u.spairs(du.args_values) do
r = r .. '| ' .. du.arg(key) .. '\n'
r = r .. '|| ' .. wu.anchor('arg', key) .. ' ' .. du.print_changes(du.args_values, key, wu.span_purple) .. '\n'
r = r .. '|-\n'
end
r = r .. '|}\n\n'
return r
end
local function print_condition_vars()
local r = ''
r = r .. string.format('==== %s ====\n', i18n.VARS_HEADER)
r = r .. '{| ' .. wu.table_class() .. '\n'
r = r .. string.format('! %s || %s \n', i18n.NAME, i18n.POSSIBLE_VALUES)
r = r .. '|-\n'
for var_name, var_values in u.spairs(du.condition_vars, du.case_order) do
r = r .. '| ' .. du.var(var_name) .. '\n'
r = r .. '|| ' .. wu.anchor('var', var_name) .. ' ' .. du.print_changes(du.condition_vars, var_name, wu.span_blue) .. '\n'
r = r .. '|-\n'
end
r = r .. '|}\n\n'
return r
end
local function print_conditions_rec(conditions, indent, colspan, prefix)
local r = ''
for i, condition in pairs(conditions) do
local if_count = 0
local then_count = 0
local is_section = false
local is_subsection = false
local has_comment = false
local has_sub_conditions = false
local description_count = 0
for param_name, param_value in pairs(condition) do
if param_name == 'verdict' or param_name == 'actions' then
then_count = then_count + 1
elseif param_name == 'section' then
is_section = true
description_count = description_count + 1
elseif param_name == 'subsection' then
is_subsection = true
description_count = description_count + 1
elseif param_name == 'comment' then
has_comment = true
description_count = description_count + 1
elseif param_name == 'sub_conditions' then
has_sub_conditions = true
else
if_count = if_count + 1
end
end
local has_conditions = (if_count > 0 or then_count > 0)
local has_descriptions = (description_count > 0)
local valign = ''
if if_count > 0 or false then -- temp
valign = "valign='top' "
end
if is_section then
r = r .. "| colspan='" .. colspan+2 .. "' style='background-color: #D4D4D4;' |\n"
r = r .. '|-\n'
elseif is_subsection then
r = r .. "| colspan='" .. colspan+2 .. "' style='background-color: #E8E8E8;' |\n"
r = r .. '|-\n'
end
local rowspan = ''
if has_conditions and has_descriptions then
rowspan = "rowspan='" .. (description_count + 1) .. "' "
end
if indent > 0 then
r = r .. "| colspan=" .. indent .. " " .. rowspan .. "| " .. '\n'
end
r = r .. "| align='center' width='1' valign='top' " .. rowspan .. "| " .. wu.anchor('condition', prefix..i) .. ' ' .. wu.link('condition '..prefix..i, wu.span_green('#' .. prefix .. i)) .. '\n'
if is_section then
r = r .. '| colspan=' .. colspan+1 .. " style='background-color: #D4D4D4;' | " .. wu.anchor('condition', i) .. ' ' .. wu.bold(i18n.SECTION .. ': ' .. wu.span_darkblue(condition)) .. '\n'
r = r .. '|-\n'
end
if is_subsection then
r = r .. '| colspan=' .. colspan+1 .. " style='background-color: #E8E8E8;' | " .. wu.anchor('condition', i) .. ' ' .. wu.bold(i18n.SUBSECTION .. ': ') .. wu.span_darkblue(condition) .. '\n'
r = r .. '|-\n'
end
if has_comment then
r = r .. '| colspan=' .. colspan+1 .. ' | ' .. wu.anchor('condition', i) .. ' ' .. wu.italic(wu.bold(i18n.COMMENT .. ': ') .. wu.span_darkblue(condition)) .. '\n'
r = r .. '|-\n'
end
if has_conditions then
r = r .. '| colspan= ' .. colspan .. ' valign="center" | '
list_prefix = ''
if if_count > 0 then
r = r .. "'''" .. i18n.IF .. "''' "
if if_count == 2 then
r = r .. wu.span_silver(string.format(" ''(%s)''", i18n.APPLY_BOTH))
elseif if_count > 2 then
r = r .. wu.span_silver(string.format(" ''(%s)''", i18n.APPLY_ALL))
end
if if_count > 1 then
r = r .. '\n'
list_prefix = '* '
end
else
r = r .. wu.span_gray(string.format("''%s''", i18n.APPLY_ALWAYS)) .. '\n'
end
for param_name, param_value in pairs(condition) do
if param_name == 'verdict' or param_name == 'actions' then
-- skip
elseif param_name == 'section' or param_name == 'subsection' or param_name == 'comment' then
-- TODO
elseif param_name == 'last' then
r = r .. list_prefix .. i18n.ENDS_WITH .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
elseif param_name == 'last_NOT' then
r = r .. list_prefix .. i18n.DOESNT_END_WITH .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
elseif param_name == 'pre_last' then -- TODO: change to "penultimate"
r = r .. list_prefix .. i18n.PRELAST_LETTER .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
elseif param_name == 'pre_last_NOT' then
r = r .. list_prefix .. i18n.PRELAST_LETTER_NOT .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
elseif param_name:match("^arg") ~= nil or param_name:match("^var") ~= nil then
local NOT = false
local var_name
if param_name:match("_NOT$") ~= nil then
NOT = true
param_name = param_name:sub(1, -5)
end
if param_name == 'arg' or param_name == 'var' then -- arg = {'<name>', <values>}
var_name = param_value
param_value = param_value
else
var_name = param_name:sub(5) -- arg_<name> = <values>
param_name = param_name:sub(1, 3)
end
if param_name == 'arg' then
r = r .. list_prefix .. i18n.SENT_ARGUMENT .. ' ' .. du.arg(var_name) .. ' '
if NOT then
r = r .. i18n.ARG_NOT_EQUAL .. ' '
else
r = r .. i18n.ARG_EQUAL .. ' '
end
r = r .. du.join_values(param_value, wu.span_purple) .. '\n'
elseif param_name == 'var' then
r = r .. list_prefix .. i18n.VAR .. ' ' .. du.var(var_name) .. ' '
if NOT then
r = r .. i18n.VAR_NOT_EQUAL .. ' '
else
r = r .. i18n.VAR_EQUAL .. ' '
end
r = r .. du.join_values(param_value, wu.span_blue) .. '\n'
end
elseif param_name == 'sub_conditions' then
-- skip
else
r = r .. list_prefix .. param_name .. ' = ' .. du.join_values(param_value, wu.span_blue) .. '\n'
end
end
r = r .. "| valign='center' | "
--if if_count > 0 then
-- r = r .. "'''" .. i18n.THEN .. "'''"
--end
r = r .. '\n'
if condition then
actions = condition
for j, action in pairs(actions) do
if action == 'set' then
local var_name = action
local var_value = du.print_action_value(action)
r = r .. i18n.SET .. ' ' .. du.var(var_name) .. ' ' .. i18n.SET_TO .. ' ' .. var_value .. '<br/>\n'
elseif action == 'add_class' then
local class_name = action
r = r .. i18n.ADD_CLASS .. ' ' .. wu.link(i18n.CLASS..' '..class_name, wu.code_olive_bold(class_name)) .. "<br/>\n"
else
r = r .. i18n.ACTION .. " '''<code style='color: purple'>" .. action .. "</code>''' (" .. action .. ")<br/>\n"
end
end
end
r = r .. '|-\n'
end
if has_sub_conditions then
r = r .. print_conditions_rec(condition, indent + 1, colspan - 1, prefix .. i .. '.')
end
end
return r
end
-- Section "Condtitions"
local function print_conditions()
-- TODO section names or groups in conditions
local conditions_depth = du.get_conditions_depth(du.conditions)
mw.log('conditions_depth =', conditions_depth)
colspan = conditions_depth + 1
local r = ''
r = r .. string.format('==== %s ====\n', i18n.CONDITIONS_HEADER)
r = r .. '{| ' .. wu.table_class() .. '\n'
r = r .. string.format('! width=1 | № || colspan=' .. colspan .. ' | %s || %s \n', i18n.CONDITIONS, i18n.ACTIONS)
r = r .. '|-\n'
r = r .. print_conditions_rec(du.conditions, 0, colspan, '')
r = r .. '|}\n\n'
return r
end
-- Section "Classes"
local function print_classes()
local r = ''
r = string.format("=== %s '''<code>classes</code>''' %s ===\n", i18n.SECTION, i18n.CLASSES_HEADER_DESC)
for class_name, forms in u.spairs(du.classes, classes_order) do
r = r .. '==== ' .. i18n.CLASS .. ' ' .. wu.code_olive_bold(class_name) .. ' ====\n'
r = r .. '{| ' .. wu.table_class() .. '\n'
r = r .. string.format('! %s || %s \n', i18n.FORM, i18n.VALUE)
r = r .. '|-\n'
for form_key, form_value in u.spairs(forms, du.case_order) do
form_value = du.print_value(form_value)
style = ''
if form_value == '—' or form_value == '-' then
style = ' align=center '
end
r = r .. '| ' .. wu.anchor('form', form_key) .. ' ' .. du.form(form_key) .. '\n'
r = r .. '|' .. style .. '| ' .. form_value .. '\n'
r = r .. '|-\n'
end
r = r .. '|}\n\n'
end
return r
end
local function print_utils()
local utils = data
-- TODO
return ''
end
local function print_notes()
local r = string.format('=== %s ===\n', i18n.NOTES_HEADER)
r = r .. '* ' .. i18n.NOTE_SENTENCE_PART1 .. ' ' .. wu.code_blue(i18n.NOTE_VAR) .. ', ' .. wu.code_purple(i18n.NOTE_ARG) .. ', ' .. wu.span_green('#1') .. ', ' .. wu.code_maroon(i18n.NOTE_FORM)
r = r .. i18n.NOTE_SENTENCE_PART2
return r
end
-- Main function to call from template
function export.get(frame)
data = load_data(frame)
du.affixes = data
du.conditions = data
du.classes = data
du.gen_form_keys()
du.gen_args_values()
du.gen_vars_changes()
local result = '\n'
result = result .. print_template_name()
result = result .. print_affixes()
result = result .. "=== " .. i18n.SECTION .. " '''<code>conditions</code>''' " .. i18n.CONDITIONS_HEADER_DESC .. " ===\n"
result = result .. print_arguments()
result = result .. print_condition_vars()
result = result .. print_conditions()
result = result .. print_classes()
result = result .. print_utils()
result = result .. print_notes()
return frame:preprocess(result)
end
return export
-- TODO: в "actions": base.replace(/k$/, 'g')
-- TODO: === Секция <code>tests</code> <span style='font-weight: normal'>''(тестовые примеры)''</span> ===
-- TODO: если секция пуста, то не отображать заголовок!!!
-- TODO: шаблон {{uz-inflection-docs}} и автоматическое определение названия дата-модуля