Module:HelperMethods: Difference between revisions

From MaRDI portal
No edit summary
No edit summary
 
(10 intermediate revisions by 2 users not shown)
Line 63: Line 63:


-- Function to convert JSON results into a Lua table with specified field order
-- Function to convert JSON results into a Lua table with specified field order
function M.convertJsonToTableOrdered(jsonResults,fieldOrder)
function M.convertJsonToTableOrdered(jsonResults, fieldOrder)
     local resultsTable = {}
     local resultsTable = {}


     if jsonResults and jsonResults.results and jsonResults.results.bindings then
     if jsonResults and jsonResults.results and jsonResults.results.bindings then
         local bindings = jsonResults.results.bindings
         local bindings = jsonResults.results.bindings
        -- Iterate through each result row in the bindings
         for j = 0, #bindings do
         for j = 0, #bindings do
             local row = {}
             local row = {}
             for _, fieldName in ipairs(fieldOrder) do
             for _, fieldName in ipairs(fieldOrder) do
                -- Extract the value from the current binding
                 local value = bindings[j][fieldName]
                 local value = bindings[j][fieldName]
                 if value then
                 if value and value.value then
                     table.insert(row, value.value)
                     table.insert(row, value.value)
                 else
                 else
                     table.insert(row, nil)
                    -- Use " " for missing or empty fields
                     table.insert(row, ' ')
                 end
                 end
             end
             end
Line 144: Line 147:
-- Function to create a HTML table from a Lua table where columns are merged
-- Function to create a HTML table from a Lua table where columns are merged
-- mergeColumns: contains a list of which columns should be merged, e.g. {{1, 2}, {4}} or {{2, 4}, {1, 3}}
-- mergeColumns: contains a list of which columns should be merged, e.g. {{1, 2}, {4}} or {{2, 4}, {1, 3}}
function M.createHtmlTableWithMergedCols(dataTable, headers, mergeColumns)
function M.createHtmlTableWithMergedCols(dataTable, headers, mergeColumns, itemprop)
     local htmlTable = mwHtml.create('table')
     local htmlTable = mwHtml.create('table')
     htmlTable:addClass('wikitable'):attr('border', '1')
     htmlTable:addClass('wikitable'):attr('border', '1')
Line 170: Line 173:
                local col1Data = row[cols[1]] or "N/A"
                local col1Data = row[cols[1]] or "N/A"
                local col2Data = row[cols[2]] or "N/A"
                local col2Data = row[cols[2]] or "N/A"
                combinedData = '[' .. col1Data .. ' ' .. col2Data .. ']'
                 
-- Check if col1Data is " "
if col1Data == " " then
    combinedData = col2Data
-- Check if both col1Data and col2Data are " "
elseif col1Data == " " and col2Data == " " then
    combinedData = " "
else
    combinedData = '[' .. col1Data .. ' ' .. col2Data .. ']'
end
if itemprop then
combinedData = combinedData .. ' <link itemprop="' .. itemprop .. '" href="' .. col1Data .. '"/> '
end
            end
            end
            dataRow:tag('td'):wikitext(combinedData)
            dataRow:tag('td'):wikitext(combinedData)
Line 179: Line 194:
     -- mw.log(htmlTable)
     -- mw.log(htmlTable)
      
      
    local javascriptSortingCode = [[
return tostring(htmlTable)
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
    var getCellValue = function (tr, idx) { return tr.children[idx].innerText || tr.children[idx].textContent; };
    var comparer = function (idx, asc) {
        return function (a, b) {
            return function (v1, v2) {
                return v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2);
            }(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
        };
    };
    var table = document.querySelector('table.sortable');
    if (table) {
        document.querySelectorAll('th').forEach(function(th) {
            th.addEventListener('click', function() {
                var table = th.closest('table');
                Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
                    .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
                    .forEach(function(tr) { table.appendChild(tr); });
            });
        });
    }
});
</script>
]]
 
--return tostring(htmlTable) .. javascriptSortingCode
return tostring(htmlTable) .. javascriptSortingCode
end
end



Latest revision as of 20:08, 16 November 2024

Documentation for this module may be created at Module:HelperMethods/doc

------------------------------------------------------------------------------------
--                                 HelperMethods                                  --
--                                                                                --
-- This module includes a number of helper functions for dealing with lists,      --
-- e.g. in the person template. It is a meta-module, meant to be called from      --
-- other Lua modules, and should not be called directly from #invoke.             --
------------------------------------------------------------------------------------


local M = {}

-- Required modules for SPARQL queries and HTML table generation
local sparql = require('SPARQL')
local mwHtml = require('mw.html')

-- Utility function to trim and lowercase a string
function M.trimAndLower(str)
	if str == nil then return nil end
	str = str:gsub("^%s*(.-)%s*$", "%1")
	return str:lower()
end

-- Utility function to count number of results in JSON answer of the SPQARL query
function M.countElementsInBindings(bindings)
	if not bindings then return 0 end
	local count = 0
	while bindings[count] do
	    count = count + 1
	end
	return count
end


-- This function will replace spaces with + and encode other non-alphanumeric 
-- characters into their percent-encoded representations, making the string 
-- safe to use in a URL.
function M.urlencode(str)
    if str then
        str = string.gsub(str, "\n", "\r\n")
        str = string.gsub(str, "([^%w %-%_%.%~])",
            function (c) return string.format("%%%02X", string.byte(c)) end)
        str = string.gsub(str, " ", "+")
    end
    return str
end


-- Function to convert JSON results into a Lua table
function M.convertJsonToTable(jsonResults)
    local resultsTable = {}
    if jsonResults and jsonResults.results and jsonResults.results.bindings then
        local bindings = jsonResults.results.bindings
        for j = 0, #bindings do
            local row = {}
            for key, value in pairs(bindings[j]) do
                table.insert(row, value.value)
            end
            table.insert(resultsTable, row)
        end
    end
    return resultsTable
end

-- Function to convert JSON results into a Lua table with specified field order
function M.convertJsonToTableOrdered(jsonResults, fieldOrder)
    local resultsTable = {}

    if jsonResults and jsonResults.results and jsonResults.results.bindings then
        local bindings = jsonResults.results.bindings
        -- Iterate through each result row in the bindings
        for j = 0, #bindings do
            local row = {}
            for _, fieldName in ipairs(fieldOrder) do
                -- Extract the value from the current binding
                local value = bindings[j][fieldName]
                if value and value.value then
                    table.insert(row, value.value)
                else
                    -- Use "&nbsp;" for missing or empty fields
                    table.insert(row, '&nbsp;')
                end
            end
            table.insert(resultsTable, row)
        end
    end

    return resultsTable
end

-- Additional function to generate the histogram data
-- colWithYear: Contains the index of the column that contains the year information. Expected format "2023-12-30"
function M.generateHistogramChartFromTable(dataTable, colWithYear)
    local yearCounts = {}

    for _, row in ipairs(dataTable) do
        -- Extract the year from the fourth column (publication date)
        local date = row[colWithYear]
        if date then  -- Check if the date exists
            local year = date:sub(1, 4)  -- Extract the year

            if year ~= "" then
                yearCounts[year] = (yearCounts[year] or 0) + 1
            end
        end
    end

    local years = {}
    local counts = {}
    for year, count in pairs(yearCounts) do
        table.insert(years, year)
        table.insert(counts, count)
    end

    -- Sort the years to maintain chronological order
    table.sort(years)
    local sortedCounts = {}
    for _, year in ipairs(years) do
        table.insert(sortedCounts, yearCounts[year])
    end

    local chartData = {
        type = 'bar',
        data = {
            labels = years,  -- x-axis labels (years)
            datasets = {{
                label = 'Number of Publications',
                data = sortedCounts,  -- y-axis data (counts)
                backgroundColor = 'rgba(54, 162, 235, 0.2)',
                borderColor = 'rgba(54, 162, 235, 1)',
                hoverBackgroundColor = 'red',
                borderWidth = 1
            }}
        },
        options = {
            scales = {
                y = {
                    beginAtZero = true
                }
            }
        }
    }

    return chartData
end


-- Function to create a HTML table from a Lua table where columns are merged
-- mergeColumns: contains a list of which columns should be merged, e.g. {{1, 2}, {4}} or {{2, 4}, {1, 3}}
function M.createHtmlTableWithMergedCols(dataTable, headers, mergeColumns, itemprop)
    local htmlTable = mwHtml.create('table')
    htmlTable:addClass('wikitable'):attr('border', '1')
    
    htmlTable:addClass('sortable') -- This line ensures your table has the 'sortable' class

    local headerRow = htmlTable:tag('tr')
    
    -- Use the provided headers
    for _, header in ipairs(headers) do
        headerRow:tag('th'):wikitext(header)
    end

    for _, row in ipairs(dataTable) do
	    if not string.find(row[1], "/entity/statement/") then
	        local dataRow = htmlTable:tag('tr')
	        
	        for _, cols in ipairs(mergeColumns) do
	            local combinedData
	            if #cols == 1 then
	                -- If only one column index is provided, use it as is, default to "N/A" string if nil
	                combinedData = row[cols[1]] or "N/A"
	            else
	                -- If two column indices are provided, merge them, defaulting to "N/A" string if nil
	                local col1Data = row[cols[1]] or "N/A"
	                local col2Data = row[cols[2]] or "N/A"
	                
					-- Check if col1Data is "&nbsp;"
					if col1Data == "&nbsp;" then
					    combinedData = col2Data
					-- Check if both col1Data and col2Data are "&nbsp;"
					elseif col1Data == "&nbsp;" and col2Data == "&nbsp;" then
					    combinedData = "&nbsp;"
					else
					    combinedData = '[' .. col1Data .. ' ' .. col2Data .. ']'
					end
					if itemprop then
						combinedData = combinedData .. ' <link itemprop="' .. itemprop .. '" href="' .. col1Data .. '"/> '
					end
	            end
	            dataRow:tag('td'):wikitext(combinedData)
	        end
	    end
    end
    
    -- mw.log(htmlTable)
    
	return tostring(htmlTable)
end

-- Helper function to convert table contents to a single string
function tableToString(t)
    local stringParts = {}
    for key, value in pairs(t) do
        if type(value) == 'string' then
            table.insert(stringParts, value)
        elseif type(value) == 'table' then
            -- Recursively convert nested tables to string
            table.insert(stringParts, tableToString(value))
        elseif type(value) == 'number' or type(value) == 'boolean' then
            -- Convert numbers and booleans to string directly
            table.insert(stringParts, tostring(value))
        end
    end
    return table.concat(stringParts, " ") -- Combine with a space as separator
end



-- Function to convert Markdown text to Mediawiki format
function M.markdownToMediawiki(mdText)

    -- Check if the input is a table and convert it
    if type(mdText) == 'table' then
        mdText = tableToString(mdText)
    elseif type(mdText) ~= 'string' then
        error("Expected a string or a table, got " .. type(mdText))
    end

    -- Process the string to convert Markdown to MediaWiki formatting
    mdText = string.gsub(mdText, "%*%*(.-)%*%*", "'''%1'''")
    mdText = string.gsub(mdText, "%[(.-)%]%((.-)%)", "[%2 %1]")
    mdText = string.gsub(mdText, "\\N", "\n")
    mdText = string.gsub(mdText, "\\T", "\t")
    mdText = string.gsub(mdText, "\n### (.-)\n", "\n=== %1 ===\n")
    mdText = string.gsub(mdText, "\n## (.-)\n", "\n== %1 ==\n")
    mdText = string.gsub(mdText, "\n# (.-)\n", "\n= %1 =\n")

    return mdText
end
return M