Line 1: |
Line 1: |
| local BaseData = require('Module:BaseData') | | local BaseData = require('Module:BaseData') |
− | | + | local Iterator = require('Module:Iterator') |
− | local format = require('Module:StringInterpolation').format | + | local format = require('Module:Core').format |
| | | |
| local BaseTable = BaseData{ | | local BaseTable = BaseData{ |
− | _table_start = [[{| class="wikitable typography-xl-optout"]], | + | _table_start = [[{| class="wikitable"]], |
| _row_starter = "|-", | | _row_starter = "|-", |
| + | _row_starter_with_attributes = [[|- class="${classes}"]], |
| _header_template = "", | | _header_template = "", |
| _column_header_cell_template = "! ${value}", | | _column_header_cell_template = "! ${value}", |
| _cell_color = { | | _cell_color = { |
| }, | | }, |
− | _cell = [[| colspan="${colspan}" rowspan="${rowspan}" style="text-align: ${text_align}; background-color: ${bg_color}; padding:3px;" |${values.value}]], | + | _cell = [[| class="${classes}" colspan="${colspan}" rowspan="${rowspan}" style="text-align:${text_align};background-color:${bg_color}" |${values.value}]], |
| + | _cell_simple = [[|${values.value}]], |
| _empty_cell = [[|]], | | _empty_cell = [[|]], |
| _column_cell_templates = { | | _column_cell_templates = { |
Line 16: |
Line 18: |
| _column_empty_cells = { | | _column_empty_cells = { |
| }, | | }, |
| + | _header1 = "<h2>${value}</h2>", |
| + | _custom_row_class = "custom-row", |
| _custom_row_prefix = "custom_row_", | | _custom_row_prefix = "custom_row_", |
| + | _classes_suffix = "_classes", |
| _text_align_suffix = "_text_align", | | _text_align_suffix = "_text_align", |
| _bg_color_suffix = "_bg_color", | | _bg_color_suffix = "_bg_color", |
Line 25: |
Line 30: |
| _emphasis_template = "'''${value}'''", | | _emphasis_template = "'''${value}'''", |
| _transparent = "transparent", | | _transparent = "transparent", |
| + | _left_align = "left", |
| _start_align = "start", | | _start_align = "start", |
| _center_align = "center", | | _center_align = "center", |
| + | _none = "none", |
| _notes_suffix = "_notes", | | _notes_suffix = "_notes", |
| _highlight_suffix = "_highlight", | | _highlight_suffix = "_highlight", |
Line 36: |
Line 43: |
| } | | } |
| | | |
− | function BaseTable:Table(args) | + | function BaseTable:Table(args, params) |
| return self{ | | return self{ |
| _args = args, | | _args = args, |
| + | _params = params, |
| }:create_table() | | }:create_table() |
| end | | end |
Line 99: |
Line 107: |
| table.insert(self._items, mw.ustring.sub(item_key, 2)) | | table.insert(self._items, mw.ustring.sub(item_key, 2)) |
| else | | else |
− | local item = self._item_class(self:process_item_key(item_key)) | + | local item = self._item_class(self:process_item_key(item_key), self._enemy) |
| table.insert(self._items, item) | | table.insert(self._items, item) |
| local note = self._args[item_key .. self._notes_suffix] | | local note = self._args[item_key .. self._notes_suffix] |
Line 125: |
Line 133: |
| row_values[column].rowspan = 1 | | row_values[column].rowspan = 1 |
| row_values[column].colspan = 1 | | row_values[column].colspan = 1 |
| + | end |
| + | --check if a row function is defined |
| + | if self.row then |
| + | --get row attributes |
| + | row_values._row = self:row(item) |
| end | | end |
| end | | end |
Line 133: |
Line 146: |
| BaseTable.create_data_rows = BaseTable.create_data_rows_plain | | BaseTable.create_data_rows = BaseTable.create_data_rows_plain |
| | | |
| + | --create the data rows, merging cells vertically between rows if they contain the same data values. |
| function BaseTable:create_data_rows_merge_vertical() | | function BaseTable:create_data_rows_merge_vertical() |
| for index, item in ipairs(self._items) do | | for index, item in ipairs(self._items) do |
Line 144: |
Line 158: |
| end | | end |
| if index > 1 then | | if index > 1 then |
| + | --This row is not the first row, we have to look at previous rows to determine if we need to merge vertically adjacent cells. |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| + | --Look on a column basis |
| for i=index-1,1,-1 do | | for i=index-1,1,-1 do |
| + | --Starting at the previous row and going to the first row. |
| local previous_row = self._data_rows[i] | | local previous_row = self._data_rows[i] |
− | local previous_row_type = type(previous_row) ~= "string" | + | local previous_row_is_data = type(previous_row) ~= "string" |
− | local previous_cell = previous_row_type and previous_row[column] or false | + | local previous_cell = previous_row_is_data and previous_row[column] or false |
| if previous_cell then | | if previous_cell then |
| + | --The previous row has a cell in the column to compare with |
| if self.compare_values(row_values[column].values, previous_cell.values) then | | if self.compare_values(row_values[column].values, previous_cell.values) then |
| + | --The cell values in the column are identical, extend the previous cell's rowspan |
| + | --and clear the cell value in the current row to merge them |
| previous_cell.rowspan = previous_cell.rowspan + 1 | | previous_cell.rowspan = previous_cell.rowspan + 1 |
| row_values[column] = nil | | row_values[column] = nil |
| else | | else |
| + | --Values don't match, set rowspan and colspan to 1 to start a new cell. |
| row_values[column].rowspan = 1 | | row_values[column].rowspan = 1 |
| row_values[column].colspan = 1 | | row_values[column].colspan = 1 |
| end | | end |
| + | --We've found the previous row that has a cell in the column, no need to look further. |
| break | | break |
− | elseif not previous_row_type then | + | elseif not previous_row_is_data then |
| + | --Previous row is not data, so we set rowspan and colspan to one to start a new cell. |
| row_values[column].rowspan = 1 | | row_values[column].rowspan = 1 |
| row_values[column].colspan = 1 | | row_values[column].colspan = 1 |
Line 166: |
Line 189: |
| end | | end |
| else | | else |
| + | --This row is the first row, we have no previous rows to look at, so set rowspan and colspan for all cells to 1 to start new cells. |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| row_values[column].rowspan = 1 | | row_values[column].rowspan = 1 |
| row_values[column].colspan = 1 | | row_values[column].colspan = 1 |
| end | | end |
| + | end |
| + | --check if a row function is defined |
| + | if self.row then |
| + | --get row attributes |
| + | row_values._row = self:row(item) |
| end | | end |
| end | | end |
Line 177: |
Line 206: |
| | | |
| function BaseTable:start_rows() | | function BaseTable:start_rows() |
− | self._rows = {self._table_start, self._header} | + | self._rows = {self._table_start} |
| + | if not self._args.no_header and self._header then |
| + | table.insert(self._rows, self._header) |
| + | end |
| end | | end |
| | | |
Line 183: |
Line 215: |
| for index, row_values in ipairs(self._data_rows) do | | for index, row_values in ipairs(self._data_rows) do |
| if row_values ~= "break" then | | if row_values ~= "break" then |
− | table.insert(self._rows, self._row_starter)
| |
| if row_values == "header" then | | if row_values == "header" then |
− | table.insert(self._rows, self._header) | + | if self._row_starter then |
− | elseif row_values == "empty" then
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | if self._header then |
| + | table.insert(self._rows, self._header) |
| + | end |
| + | elseif row_values == "empty" then |
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| table.insert(self._rows, self._column_empty_cells[column] or self._empty_cell) | | table.insert(self._rows, self._column_empty_cells[column] or self._empty_cell) |
| end | | end |
| elseif type(row_values) == "table" then | | elseif type(row_values) == "table" then |
| + | if row_values._row then |
| + | if self._row_starter_with_attributes then |
| + | table.insert(self._rows, format(self._row_starter_with_attributes, row_values._row)) |
| + | end |
| + | else |
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | end |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| if row_values[column] then | | if row_values[column] then |
− | table.insert(self._rows, format(self._column_cell_templates[column] or self._cell, row_values[column])) | + | if row_values[column].bg_color and row_values[column].bg_color ~= self._transparent then |
| + | row_values[column].classes = "highlighted " .. (row_values[column].classes or "") |
| + | end |
| + | if row_values[column].simple then |
| + | table.insert(self._rows, format(self._cell_simple, row_values[column])) |
| + | else |
| + | table.insert(self._rows, format(self._column_cell_templates[column] or self._cell, row_values[column])) |
| + | end |
| end | | end |
| end | | end |
Line 206: |
Line 261: |
| function BaseTable:build_rows_breaks_as_empty_rows() | | function BaseTable:build_rows_breaks_as_empty_rows() |
| for index, row_values in ipairs(self._data_rows) do | | for index, row_values in ipairs(self._data_rows) do |
− | table.insert(self._rows, self._row_starter)
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| if row_values == "break" then | | if row_values == "break" then |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| table.insert(self._rows, self._column_empty_cells[column] or self._empty_cell) | | table.insert(self._rows, self._column_empty_cells[column] or self._empty_cell) |
| end | | end |
− | elseif row_values == "header" then | + | elseif row_values == "header" and self._header then |
| table.insert(self._rows, self._header) | | table.insert(self._rows, self._header) |
| elseif type(row_values) == "table" then | | elseif type(row_values) == "table" then |
| for _, column in ipairs(self._columns) do | | for _, column in ipairs(self._columns) do |
| if row_values[column] then | | if row_values[column] then |
− | table.insert(self._rows, format(self._column_cell_templates[column] or self._cell, row_values[column])) | + | if row_values[column].simple then |
| + | table.insert(self._rows, format(self._cell_simple, row_values[column])) |
| + | else |
| + | table.insert(self._rows, format(self._column_cell_templates[column] or self._cell, row_values[column])) |
| + | end |
| end | | end |
| end | | end |
Line 226: |
Line 287: |
| | | |
| function BaseTable:append_custom_row(custom_row_key) | | function BaseTable:append_custom_row(custom_row_key) |
− | table.insert(self._rows,
| + | if mw.ustring.sub(custom_row_key, 1, 1) == "#" then |
− | format{self._column_cell_templates["!"] or self._cell, | + | local value = mw.ustring.sub(custom_row_key, 2) |
− | colspan = #self._columns, rowspan = 1, | + | if not self._disable_row_starter and self._row_starter then |
− | text_align = self._args[self._custom_row_prefix .. custom_row_key .. self._text_align_suffix] or self._start_align, | + | table.insert(self._rows, self._row_starter) |
− | bg_color = self._args[self._custom_row_prefix .. custom_row_key .. self._bg_color_suffix] or self._transparent, | + | end |
| + | table.insert(self._rows, format{ |
| + | self._cell, |
| + | colspan = #self._columns, rowspan = 1, |
| + | classes = self._custom_row_class, |
| + | text_align = self._left_align, |
| + | bg_color = self._transparent, |
| values = { | | values = { |
− | value = self._args[self._custom_row_prefix .. custom_row_key .. self._content_suffix] or "", | + | value = format{ |
| + | self._header1, |
| + | value = value |
| + | } |
| }, | | }, |
− | } | + | }) |
− | ) | + | if not self._disable_row_starter and self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | if not self._disable_row_starter and self._header then |
| + | table.insert(self._rows, self._header) |
| + | end |
| + | elseif self._custom_rows and self._custom_rows[custom_row_key] then |
| + | if type(self._custom_rows[custom_row_key]) == "table" then |
| + | if self._row_starter_with_attributes then |
| + | table.insert(self._rows, format(self._row_starter_with_attributes, self._custom_rows[custom_row_key].row or {})) |
| + | end |
| + | table.insert(self._rows, self._custom_rows[custom_row_key].content) |
| + | else |
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | table.insert(self._rows, self._custom_rows[custom_row_key]) |
| + | end |
| + | else |
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | local classes = self._args[self._custom_row_prefix .. custom_row_key .. self._classes_suffix] |
| + | if classes then |
| + | classes = " " .. classes |
| + | else |
| + | classes = "" |
| + | end |
| + | table.insert(self._rows, |
| + | format{self._column_cell_templates["!"] or self._cell, |
| + | colspan = #self._columns, rowspan = 1, |
| + | classes = self._custom_row_class .. classes, |
| + | text_align = self._args[self._custom_row_prefix .. custom_row_key .. self._text_align_suffix] or self._start_align, |
| + | bg_color = self._args[self._custom_row_prefix .. custom_row_key .. self._bg_color_suffix] or self._transparent, |
| + | values = { |
| + | value = self._args[self._custom_row_prefix .. custom_row_key .. self._content_suffix] or "", |
| + | }, |
| + | } |
| + | ) |
| + | end |
| end | | end |
| | | |
| function BaseTable:finish_rows() | | function BaseTable:finish_rows() |
− | table.insert(self._rows, self._row_starter)
| + | if not self._args.no_header_bottom then |
− | table.insert(self._rows, self._header_bottom or self._header)
| + | if self._row_starter then |
| + | table.insert(self._rows, self._row_starter) |
| + | end |
| + | if self._header_bottom or self._header then |
| + | table.insert(self._rows, self._header_bottom or self._header) |
| + | end |
| + | end |
| table.insert(self._rows, self._table_end) | | table.insert(self._rows, self._table_end) |
| end | | end |
| | | |
| function BaseTable:join_rows() | | function BaseTable:join_rows() |
− | return table.concat(self._rows, "\n") | + | self._result = table.concat(self._rows, "\n") |
| + | end |
| + | |
| + | function BaseTable:prepare_iterator() |
| + | local buildIterator = Iterator[self._args.iterator] |
| + | if buildIterator then |
| + | local iterator = buildIterator(self._args) |
| + | while iterator.next() do |
| + | table.insert(self._args, iterator.current()) |
| + | end |
| + | end |
| + | buildIterator = Iterator[self._args.iterator2] |
| + | if buildIterator then |
| + | table.insert(self._args, "#") |
| + | local iterator = buildIterator(self._args, 2) |
| + | while iterator.next() do |
| + | table.insert(self._args, iterator.current()) |
| + | end |
| + | end |
| end | | end |
| | | |
Line 253: |
Line 386: |
| | | |
| function BaseTable:create_items_post() | | function BaseTable:create_items_post() |
| + | return |
| + | end |
| + | |
| + | function BaseTable:post_process() |
| return | | return |
| end | | end |
Line 260: |
Line 397: |
| self._notes = {} | | self._notes = {} |
| self._data_rows = {} | | self._data_rows = {} |
| + | self:prepare_iterator() |
| self:create_table_prep() | | self:create_table_prep() |
| | | |
Line 270: |
Line 408: |
| self:build_rows() | | self:build_rows() |
| self:finish_rows() | | self:finish_rows() |
− | return self:join_rows() | + | self:join_rows() |
| + | self:post_process() |
| + | return self._result |
| end | | end |
| | | |
| return BaseTable | | return BaseTable |