Module:Sandbox/Aseleste/Indexer/sandbox explained

-- Categorizes content and display them.-- Improvements are welcomed.

-- requires

-- forward declarationslocal index;local process_key_value;local build_keys;local build_values;local as_key_content_function;local as_value_content_function;local as_fold_function;local escape_replacement;local unstrip_and_strip_nowiki_tags;

-- exposed: categorizes content and display them-- 'folder', 'table_*', 'content'index = function(frame) local args = build_args(frame) local folder = as_fold_function(args.folder) local keys, key_order = build_keys(args) local values = build_values(args.content) local result = "" -- ordered first for _, categories in ipairs(key_order) do for _, category in ipairs(categories) do local processed = process_key_value(keys, values, category) if processed then result = folder(result, processed) -- remove key and value to mark as processed keys[category] = nil values[category] = nil end end end -- unordered last for category, _ in pairs(keys) do local processed = process_key_value(keys, values, category) if processed then result = folder(result, processed) end end return frame:getParent:preprocess(result) -- intended to be used with a templateend

-- process key and value for a given categoryprocess_key_value = function(keys, values, category) local key = keys[category] if key then local value = values[category] if not value then value = function(category) return "" end end local result = key(value(category)) return result end return nilend

-- builds arguments-- reads parent framebuild_args = function(frame) local result = for key, value in pairs(frame.args) do result[mw.text.trim(key)] = mw.text.trim(unstrip_and_strip_nowiki_tags(value)) end local pframe = frame:getParent for key, value in pairs(pframe.args) do result[mw.text.trim(key)] = mw.text.trim(unstrip_and_strip_nowiki_tags(value)) end return resultend

-- builds key mapping, key order mapping-- reads 'table_*'build_keys = function(args) local keys = local key_order = for arg_k, arg_v in pairs(args) do if arg_k:match("^table_") then local key = arg_k:gsub("table_", "", 1) local order = key:match("^(%d+)_") if order then key = key:gsub(order .. "_", "", 1) local order_list = key_order[order] if order_list then table.insert(order_list, key) else key_order[order] = end end keys[key] = as_key_content_function(arg_v) end end -- sort key order local key_order_list = for order, category in pairs(key_order) do table.insert(key_order_list,) end table.sort(key_order_list, function(a, b) return a.key < b.key end) key_order = for _, value in ipairs(key_order_list) do table.insert(key_order, value.value) end return keys, key_orderend

-- builds values mapping-- magic words: '__M_INDEX__'-- syntax: '__M_INDEX__ [category1] [category2] ... [categoryN]'build_values = function(text) -- need cleanup local result = local context = local content = "" for _, line in ipairs(mw.text.split(text, "\n", true)) do -- is \n sufficient if line:match("^__M_INDEX__") then -- finish result for _, category in ipairs(context) do local sub_result = result[category] if sub_result

nil then result[category] = content else result[category] = sub_result .. content end end content = "" -- change context context = for category in line:gmatch("%[([^%]]*)%]") do table.insert(context, category) end else -- append content content = content .. line .. "\n" end end -- one more round of finishing result for _, category in ipairs(context) do local sub_result = result[category] if sub_result

nil then result[category] = content else result[category] = sub_result .. content end end -- turn into content function for key, value in pairs(result) do result[key] = as_value_content_function(value) end return resultend

-- converts text to key content function-- magic words: '__M_CONTENT__'as_key_content_function = function(text) local function func(content) local result = text:gsub("__M_CONTENT__", escape_replacement(content)) -- need this variable to only return 1 result return result end return funcend

-- converts text to value content function-- magic words: '__M_CATEGORY__'as_value_content_function = function(text) local function func(category) local result = text:gsub("__M_CATEGORY__", escape_replacement(category)) -- need this variable to only return 1 result return result end return funcend

-- converts text to folding function-- magic words: '__M_LEFT__', '__M_RIGHT__'as_fold_function = function(text) local function func(left, right) -- some improvements could be made here local result = text:gsub("__M_LEFT__", escape_replacement(left)):gsub("__M_RIGHT__", escape_replacement(right)) -- need this variable to only return 1 result return result end return funcend

-- escapes replacement, replace '%' with '%%'-- ah, multiple return results cost us headache, apparently multiple return results expand into multiple argumentsescape_replacement = function(text) local result = text:gsub("%%", "%%%%") -- need this variable to only return 1 result return resultend

unstrip_and_strip_nowiki_tags = function(text) local result = mw.text.unstripNoWiki(text) -- need this variable to only return 1 result :gsub("", "") :gsub("", "") :gsub("<", "<") -- needs to be escaped in the source :gsub(">", ">") :gsub(""", '"') return resultend

return