Module:Ref info

-- This module counts the number of times that various reference tags and cs1|2 templates appear.

-- {{#invoke:ref_info|ref_info}}

-- {{ref info}}

-- {{ref info|aristotle}}

require('strict');

local data = mw.loadData ('Module:Ref info/data');

--mw.logObject (data.cs12_stripped_list, 'data.cs12_stripped_list')

local collapsible_tables = {

['cs1'] = '', -- collapsible wiki-tables of names and counts

['cs2'] = '',

['cs1_like'] = '',

['vcite'] = '',

['sfn'] = '',

['harv'] = '',

}

--[[--------------------------< T E M P L A T E _ N A M E _ T A B L E _ M A K E >------------------------------

makes a collapsed html table that holds a list of cs1 or cs2 template used in an article. The list occupies a

single row of the parent table.

]]

local function template_name_table_make (name_list, group)

local name_table = {};

local function comp (a, b) -- used in following table.sort()

return a:lower() < b:lower(); -- case-insensitive ascending alpha sort

end

table.insert (name_table, '\n|-\n|scope="row" colspan="2" style="vertical-align:top;text-align:left" |\n'); -- create a blank row in parent table for this table

table.insert (name_table, '

class="mw-collapsible mw-collapsed nowrap" style="margin: 0.2em auto auto; width:100%;"\n') -- open the collapsed list table; style aligns show/hide toggle

table.insert (name_table, '| List of '); -- begin simple header row always displays

table.insert (name_table, group); -- template group (cs1, cs2 TODO: vcite? harv?)

table.insert (name_table, ' templates \n'); -- end of simple heading

table.insert (name_table, '

\n|\n
    \n'); -- new row, row content begins with
    ; open unordered list

    local t = {};

    for k, v in pairs (name_list) do -- spin through the list

    table.insert (t, string.format ('

  • %s (%s)
  • ', k, v)) -- make pretty unordered list of name with count

    end

    if not t[1] then

    return ''; -- nothing in the list so abandon

    end

    table.sort (t, comp); -- case-insensitive ascending alpha sort

    table.insert (t, '

\n'); -- close unordered list

table.insert (name_table, table.concat (t, '\n')); -- make a string and add to main table

table.insert (name_table, '\n

'); -- close the table

return table.concat (name_table); -- return html table as a string

end

--[[--------------------------< C O L L E C T _ T E M P L A T E S >--------------------------------------------

function to collect every template

]]

local function collect_templates (Article_content)

local template_list = {};

local tstart, tend = Article_content:find ("{{%s*[^|}]+%s*[|}]"); -- find the first template

while tstart do -- nil when template not found

local template = Article_content:match ('%b{}', tstart); -- get the whole template

if template then

template_list[#template_list+1] = template

end

tstart = tend; -- reset the search starting index

tstart, tend = Article_content:find ("{{%s*[^|}]+%s*[|}]", tstart); -- search for another template

end

return template_list;

end

--[[--------------------------< C O U N T _ P A T T E R N >----------------------------------------------------

this is a general purpose function used to count occurrences of in

]]

local function count_pattern (text, pattern)

local _;

local count;

_, count = mw.ustring.gsub (text, pattern, '%1');

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ L A S T >--------------------------------------------------

makes a count of those cs1|2 templates that use |last= or |last1= (or any of the selected aliases of these).

]]

local function count_cs1_last (template, count)

local _, tally;

for _, param in ipairs (data.last_param_patterns) do

_, tally = mw.ustring.gsub (template, '|%s*' .. param .. '%s*=%s*[^}|]', '%1'); -- count occurences of that pattern

count = count + tally; -- accumulate a total

end

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ A U T H O R >----------------------------------------------

makes a count of those cs1|2 templates that use |author= or |author1= (or any of the selected aliases of these).

]]

local function count_cs1_author (template, count)

local _, tally;

for _, param in ipairs (data.author_param_patterns) do

_, tally = mw.ustring.gsub (template, '|%s*' .. param .. '%s*=%s*[^}|]', '%1'); -- count occurences of that pattern

count = count + tally; -- accumulate a total

end

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ A U T H O R S >--------------------------------------------

makes a count of those cs1|2 templates that use |authors= (or any of the selected aliases).

]]

local function count_cs1_authors (template, count)

local _, tally;

for _, param in ipairs (data.authors_param_patterns) do

_, tally = mw.ustring.gsub (template, '|%s*' .. param .. '%s*=%s*[^}|]', '%1'); -- count occurences of that pattern

count = count + tally; -- accumulate a total

end

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ V A U T H O R S >------------------------------------------

makes a count of those cs1|2 templates that use |vauthors=.

]]

local function count_cs1_vauthors (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*vauthors%s*=%s*[^}|]', '%1'); -- count occurences of that pattern

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ D M Y >----------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |date=DD Month YYYY where

DD is one or two digits or a range DD-DD Month YYYY

]]

local function count_cs1_dates_dmy (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*date%s*=%s*%d?%d%s+%a+%s+%d%d%d%d', '%1'); -- dd Month yyyy

count = count + tally; -- accumulate a total

_, tally = mw.ustring.gsub (template, '|%s*date%s*=%s*%d?%d[%-–]%d?%d%s+%a+%s+%d%d%d%d', '%1'); -- dd-dd Month yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ M D Y >----------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |date=Month DD, YYYY where

DD is one or two digits or a range Month DD-DD, YYYY

]]

local function count_cs1_dates_mdy (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*date%s*=%s*%a+%s+%d?%d%s*,%s+%d%d%d%d', '%1'); -- Month dd, yyyy

count = count + tally; -- accumulate a total

_, tally = mw.ustring.gsub (template, '|%s*date%s*=%s*%a+%s+%d?%d[%-–]%d?%d%s*,%s+%d%d%d%d', '%1'); -- Month dd-dd, yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ Y M D >----------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |date=YYYY-MM-DD

]]

local function count_cs1_dates_ymd (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*date%s*=%s*%d%d%d%d%-%d%d%-%d%d', '%1'); -- yyyy-mm-dd

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ D M Y _ A C C E S S >--------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |access-date=DD Month YYYY where

DD is one or two digits or a range DD-DD Month YYYY

]]

local function count_cs1_dates_dmy_access (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*access%-?date%s*=%s*%d?%d%s+%a+%s+%d%d%d%d', '%1'); -- dd Month yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ M D Y _ A C C E S S >--------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |accesss-date=Month DD, YYYY where

DD is one or two digits or a range Month DD-DD, YYYY

]]

local function count_cs1_dates_mdy_access (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*access%-?date%s*=%s*%a+%s+%d?%d%s*,%s+%d%d%d%d', '%1'); -- Month dd, yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ Y M D _ A C C E S S >--------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |access-date=YYYY-MM-DD

]]

local function count_cs1_dates_ymd_access (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*access%-?date%s*=%s*%d%d%d%d%-%d%d%-%d%d', '%1'); -- yyyy-mm-dd

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ D M Y _ A R C H I V E >------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |archive-date=DD Month YYYY where

DD is one or two digits or a range DD-DD Month YYYY

]]

local function count_cs1_dates_dmy_archive (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*archive%-?date%s*=%s*%d?%d%s+%a+%s+%d%d%d%d', '%1'); -- dd Month yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ M D Y _ A R C H I V E >------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |archive-date=Month DD, YYYY where

DD is one or two digits or a range Month DD-DD, YYYY

]]

local function count_cs1_dates_mdy_archive (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*archive%-?date%s*=%s*%a+%s+%d?%d%s*,%s+%d%d%d%d', '%1'); -- Month dd, yyyy

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D A T E S _ Y M D _ A R C H I V E >------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |archive-date=YYYY-MM-DD

]]

local function count_cs1_dates_ymd_archive (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*archive%-?date%s*=%s*%d%d%d%d%-%d%d%-%d%d', '%1'); -- yyyy-mm-dd

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D F _ D M Y >----------------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |df=xxx (with a value)

]]

local function count_cs1_df_dmy (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*df%s*=%s*dmy%-?a?l?l?', '%1'); -- |df=dmy |df=dmy-all

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D F _ M D Y >----------------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |df=xxx (with a value)

]]

local function count_cs1_df_mdy (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*df%s*=%s*mdy%-?a?l?l?', '%1'); -- |df=mdy |df=mdy-all

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 _ D F _ Y M D >----------------------------------------------

Using the lists of cs1|2 templates, make a count of just those templates that have |df=xxx (with a value)

]]

local function count_cs1_df_ymd (template, count)

local _, tally;

_, tally = mw.ustring.gsub (template, '|%s*df%s*=%s*ymd%-?a?l?l?', '%1'); -- |df=ymd |df=ymd-all

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C O U N T _ C S 1 2 _ M O D E >--------------------------------------------------

make a count of those cs1|2 templates that have |mode=cs1 or |mode=cs2

]]

local function count_cs12_mode (template, count, mode)

local _, tally;

mode = 1 == mode and 'cs1' or 'cs2';

_, tally = mw.ustring.gsub (template, '|%s*mode%s*=%s*' .. mode, '%1'); -- |mode=cs1 or |mode=cs2

count = count + tally; -- accumulate a total

return count;

end

--[[--------------------------< C S 1 _ C S 2 _I N F O _ G E T >-----------------------------------------------

Using the list of cs1|2 templates, make a count of those templates. Make lists of cs1|2 templates used. Count

different author-name styles, date styles.

]]

local function cs1_cs2_info_get (template_list, pattern, template_name_list, object)

local total = 0;

for _, template in ipairs (template_list) do -- go through all cs1|2 like templates

if template:match("^" .. pattern) then

local name = template:match ('^{{%s*([^|}]-)%s*[|}]'); -- get template name

if not template_name_list[name] then -- if not already saved

template_name_list[name] = 1; -- save it

else -- here when this name already saved

template_name_list[name] = template_name_list[name] + 1; -- to indicate that there are multiple same name templates

end

total = total + 1; -- tally total number of cs1 templates

-- count various date properties

object['cs1_dmy_dates']['count'] = count_cs1_dates_dmy (template, object['cs1_dmy_dates']['count']); -- count of |date=dmy

object['cs1_mdy_dates']['count'] = count_cs1_dates_mdy (template, object['cs1_mdy_dates']['count']); -- count of |date=mdy

object['cs1_ymd_dates']['count'] = count_cs1_dates_ymd (template, object['cs1_ymd_dates']['count']); -- count of |date=ymd

object['cs1_dmy_dates_access']['count'] = count_cs1_dates_dmy_access (template, object['cs1_dmy_dates_access']['count']); -- count of |access-date=dmy

object['cs1_mdy_dates_access']['count'] = count_cs1_dates_mdy_access (template, object['cs1_mdy_dates_access']['count']); -- count of |access-date=mdy

object['cs1_ymd_dates_access']['count'] = count_cs1_dates_ymd_access (template, object['cs1_ymd_dates_access']['count']); -- count of |access-date=ymd

object['cs1_dmy_dates_archive']['count'] = count_cs1_dates_dmy_archive (template, object['cs1_dmy_dates_archive']['count']); -- count of |archive-date=dmy

object['cs1_mdy_dates_archive']['count'] = count_cs1_dates_mdy_archive (template, object['cs1_mdy_dates_archive']['count']); -- count of |archive-date=mdy

object['cs1_ymd_dates_archive']['count'] = count_cs1_dates_ymd_archive (template, object['cs1_ymd_dates_archive']['count']); -- count of |archive-date=ymd

object['cs1_dates_df_dmy']['count'] = count_cs1_df_dmy (template, object['cs1_dates_df_dmy']['count']); -- count of |df=dmy

object['cs1_dates_df_mdy']['count'] = count_cs1_df_mdy (template, object['cs1_dates_df_mdy']['count']); -- count of |df=dmy

object['cs1_dates_df_ymd']['count'] = count_cs1_df_ymd (template, object['cs1_dates_df_ymd']['count']); -- count of |df=dmy

-- count various author-name properties

object['cs1_last']['count'] = count_cs1_last (template, object['cs1_last']['count']); -- count of |lastn=

object['cs1_author']['count'] = count_cs1_author (template, object['cs1_author']['count']); -- count of |authorn=

object['cs1_authors']['count'] = count_cs1_authors (template, object['cs1_authors']['count']); -- count of |authors=

object['cs1_vauthors']['count'] = count_cs1_vauthors (template, object['cs1_vauthors']['count']); -- count of |vauthors=

object['cs1_mode']['count'] = count_cs12_mode (template, object['cs1_mode']['count'], 1); -- count of |mode=cs1

object['cs2_mode']['count'] = count_cs12_mode (template, object['cs2_mode']['count'], 2); -- count of |mode=cs2

end

end

return total;

end

--[[--------------------------< C O U N T _ C S 1 >------------------------------------------------------------

Using the list of cs1 templates, make a count of just those templates as dictated by base_pattern.

makes a list of cs1 templates in the article

]]

local function count_cs1 (Article_content, base_pattern, object)

local pattern;

local total = 0;

local cs1_template_name_list = {};

local templates = collect_templates (Article_content)

for i, cs1_template in ipairs (data.cs1_template_patterns) do

pattern = string.format (base_pattern, cs1_template); -- make a pattern for the selected cs1 template

total = total + cs1_cs2_info_get (templates, pattern, cs1_template_name_list, object);

end

collapsible_tables.cs1 = template_name_table_make (cs1_template_name_list, 'cs1');

--mw.logObject (cs1_template_name_list, 'cs1_template_name_list')

return total;

end

--[[--------------------------< C O U N T _ C S 1 _ R E F S >--------------------------------------------------

Using the list of cs1 templates, make a count of just those references as dictated by base_pattern.

]]

local function count_cs1_refs (text, base_pattern)

local _;

local pattern;

local count, total = 0, 0;

for i, template in ipairs (data.cs1_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected cs1 template

_, count = mw.ustring.gsub (text, pattern, '%1'); -- count occurences of that pattern

total = total + count; -- accumulate a total

end

return total;

end

--[[--------------------------< C O U N T _ C S 1 _ L I K E _ T E M P L A T E S >------------------------------

make a count of cs1-like templates as dictated by .

]]

local function count_cs1_like_templates (Article_content, pattern)

local tstart, tend = Article_content:find (pattern); -- find the first cs1-like template

local total = 0;

local template_name_list = {};

while tstart do -- nil when cs1-like template not found

local template = Article_content:match ('%b{}', tstart); -- get the template in the ref

if template then -- necessary?

local name = template:match ('{{%s*([^|}]-)%s*[|}]'); -- get template name

name = name:gsub (' +', ' '); -- replace multiple space chars with a single char

if not data.cs12_stripped_list[name] then -- if not a cs1|2 template

if not template_name_list[name] then -- if not already saved

template_name_list[name] = 1; -- save it

else -- here when this name already saved

template_name_list[name] = template_name_list[name] + 1; -- to indicate that there are multiple same name templates

end

total = total + 1; -- tally total number of cs1-like templates

end

end

tstart = tend; -- reset the search starting index

tstart, tend = Article_content:find (pattern, tstart); -- search for another cs1|2 template

end

collapsible_tables.cs1_like = template_name_table_make (template_name_list, 'cs1-like');

return total;

end

--[[--------------------------< C O U N T _ C S 1 _ L I K E _ R E F S >----------------------------------------

make a count of cs1-like references as dictated by .

]]

local function count_cs1_like_refs (Article_content, pattern)

local tstart, tend = Article_content:find (pattern); -- find the first cs1-like template

local total = 0;

while tstart do -- nil when cs1-like reference not found

local template = Article_content:match ('%b{}', tstart); -- get the template in the ref

if template then -- necessary?

local name = template:match ('{{%s*([^|}]-)%s*[|}]'); -- get template name

name = name:gsub (' +', ' '); -- replace multiple space chars with a single char

if not data.cs12_stripped_list[name] then -- if not a cs1|2 template

total = total + 1; -- tally total number of cs1-like references

end

end

tstart = tend; -- reset the search starting index

tstart, tend = Article_content:find (pattern, tstart); -- search for another cs1|2 template

end

return total;

end

--[[--------------------------< C O U N T _ C S 2 >------------------------------------------------------------

Using the list of cs2 templates, make a count of those templates as dictated by base_pattern.

make a list of cs2 templates in the article

]]

local function count_cs2 (Article_content, base_pattern, object)

local pattern;

local count, total = 0, 0;

local cs2_template_name_list = {};

local templates = collect_templates (Article_content)

for i, cs2_template in ipairs (data.cs2_template_patterns) do

pattern = string.format (base_pattern, cs2_template); -- make a pattern for the selected cs2 template

total = total + cs1_cs2_info_get (templates, pattern, cs2_template_name_list, object);

end

collapsible_tables.cs2 = template_name_table_make (cs2_template_name_list, 'cs2');

--mw.logObject (cs2_template_name_list, 'cs2_template_name_list')

return total;

end

--[[--------------------------< C O U N T _ C S 2 _ R E F S >--------------------------------------------------

Using the list of cs2 templates, make a count of those references as dictated by base_pattern.

]]

local function count_cs2_refs (text, base_pattern)

local _;

local pattern;

local count, total = 0, 0;

for i, template in ipairs (data.cs2_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected cs1 template

_, count = mw.ustring.gsub (text, pattern, '%1'); -- count occurences of that pattern

total = total + count; -- accumulate a total

end

return total;

end

--[[--------------------------< C O U N T _ V C I T E >--------------------------------------------------------

Using the list of vcite templates, make a count of just those templates as dictated by base_pattern.

makes a list of vcite templates in the article

]]

local function count_vcite (Article_content, base_pattern, object)

local _;

local pattern;

local total = 0;

local templates = collect_templates (Article_content)

local vcite_template_name_list = {};

for i, vcite_template in ipairs (data.vcite_template_patterns) do

pattern = string.format (base_pattern, vcite_template); -- make a pattern for the selected vcite template

for _, template in ipairs (templates) do

if template:match ("^" .. pattern) then

local name = template:match ('^{{%s*([^|}]-)%s*[|}]'); -- get template name

if not vcite_template_name_list[name] then -- if not already saved

vcite_template_name_list[name] = 1; -- save it

else -- here when this name already saved

vcite_template_name_list[name] = vcite_template_name_list[name] + 1; -- to indicate that there are multiple same name templates

end

total = total + 1; -- tally total number of vcite templates

end

end

end

collapsible_tables.vcite = template_name_table_make (vcite_template_name_list, 'vcite');

--mw.logObject (vcite_template_name_list, 'vcite_template_name_list')

return total;

end

--[[--------------------------< C O U N T _ V C I T E _ R E F S >----------------------------------------------

Using the list of cs1 templates, make a count of just those references as dictated by base_pattern.

]]

local function count_vcite_refs (text, base_pattern)

local _;

local pattern;

local count, total = 0, 0;

for i, template in ipairs (data.vcite_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected vcite template

_, count = mw.ustring.gsub (text, pattern, '%1'); -- count occurences of that pattern

total = total + count; -- accumulate a total

end

return total;

end

--[[--------------------------< S F N _ H A R V _I N F O _ G E T >---------------------------------------------

Using the list of sfn and harv templates, make a count of those templates. Make lists of sfn and harv templates

used.

]]

local function sfn_harv_info_get (templates, pattern, template_name_list, object)

local total = 0;

for _, template in ipairs (templates) do

if template:match ("^" .. pattern) then

local name = template:match ('{{%s*([^|}]-)%s*[|}]'); -- get template name

if not template_name_list[name] then -- if not already saved

template_name_list[name] = 1; -- save it

else -- here when this name already saved

template_name_list[name] = template_name_list[name] + 1; -- to indicate that there are multiple same name templates

end

total = total + 1; -- tally total number of templates

end

end

return total;

end

--[[--------------------------< C O U N T _ S F N >------------------------------------------------------------

Using the list of sfn templates, make a count of just those templates as dictated by base_pattern.

makes a list of sfn templates in the article

]]

local function count_sfn (Article_content, base_pattern, object)

local _;

local pattern;

local total = 0;

local templates = collect_templates (Article_content)

local sfn_template_name_list = {};

for i, sfn_template in ipairs (data.sfn_template_patterns) do

pattern = string.format (base_pattern, sfn_template); -- make a pattern for the selected template

total = total + sfn_harv_info_get (templates, pattern, sfn_template_name_list, object);

end

collapsible_tables.sfn = template_name_table_make (sfn_template_name_list, 'sfn');

--mw.logObject (sfn_template_name_list, 'sfn_template_name_list')

return total;

end

--[[--------------------------< C O U N T _ H A R V >----------------------------------------------------------

Using the list of harv templates, make a count of just those templates as dictated by base_pattern.

makes a list of harv templates in the article

]]

local function count_harv (Article_content, base_pattern, object)

local _;

local pattern;

local total = 0;

local templates = collect_templates (Article_content)

local harv_template_name_list = {};

for i, harv_template in ipairs (data.harv_template_patterns) do

pattern = string.format (base_pattern, harv_template); -- make a pattern for the selected template

total = total + sfn_harv_info_get (templates, pattern, harv_template_name_list, object);

end

collapsible_tables.harv = template_name_table_make (harv_template_name_list, 'harv');

--mw.logObject (harv_template_name_list, 'harv_template_name_list')

return total;

end

--[[--------------------------< C O U N T _ H A R V _ R E F S >------------------------------------------------

Using the list of harv templates, make a count of those references as dictated by base_pattern.

]]

local function count_harv_refs (text, base_pattern)

local _;

local pattern;

local count, total = 0, 0;

for i, template in ipairs (data.harv_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected cs1 template

_, count = mw.ustring.gsub (text, pattern, '%1'); -- count occurences of that pattern

total = total + count; -- accumulate a total

end

return total;

end

--[[--------------------------< C O U N T _ R E F B E G I N >--------------------------------------------------

Using the list of cleanup templates, make a count of those templates as dictated by base_pattern.

]]

local function count_refbegin (text, base_pattern)

local _;

local pattern;

local template_list = collect_templates (text)

local count, total = 0, 0;

for i, template in ipairs (data.refbegin_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected template

for _, template in ipairs(template_list) do

if template:match ("^" .. pattern) then

total = total + 1

end

end

end

return total;

end

--[[--------------------------< C O U N T _ R P >--------------------------------------------------------------

Using the list of cleanup templates, make a count of those templates as dictated by base_pattern.

]]

local function count_rp (text, base_pattern)

local _;

local pattern;

local template_list = collect_templates (text)

local count, total = 0, 0;

for i, template in ipairs (data.rp_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected template

for _, template in ipairs(template_list) do

if template:match ("^" .. pattern) then

total = total + 1

end

end

end

return total;

end

--[[--------------------------< C O U N T _ C L E A N U P >----------------------------------------------------

Using the list of cleanup templates, make a count of those templates as dictated by base_pattern.

]]

local function count_cleanup (text, base_pattern)

local _;

local pattern;

local template_list = collect_templates (text)

local count, total = 0, 0;

for i, template in ipairs (data.cleanup_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected cleanup template

for _, template in ipairs(template_list) do

if template:match ("^" .. pattern) then

total = total + 1

end

end

end

return total;

end

--[[--------------------------< C O U N T _ D E A D _ L I N K S >----------------------------------------------

Using the list of dead link templates, make a count of those templates as dictated by base_pattern.

]]

local function count_dead_links (text, base_pattern)

local _;

local pattern;

local template_list = collect_templates (text)

local count, total = 0, 0;

for i, template in ipairs (data.dead_link_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected template

for _, template in ipairs(template_list) do

if template:match ("^" .. pattern) then

total = total + 1

end

end

end

return total;

end

--[[--------------------------< C O U N T _ W E B A R C H I V E >----------------------------------------------

Using the list of webarchive aliases, make a count of those templates as dictated by base_pattern.

]]

local function count_webarchive (text, base_pattern)

local _;

local pattern;

local template_list = collect_templates (text)

local count, total = 0, 0;

for i, template in ipairs (data.webarchive_template_patterns) do

pattern = string.format (base_pattern, template); -- make a pattern for the selected template

for _, template in ipairs(template_list) do

if template:match ("^" .. pattern) then

total = total + 1

end

end

end

return total;

end

--[[--------------------------< H A S _ L D R >----------------------------------------------------------------

returns a string set to 'yes' if the article uses list defined references. ldr uses {{reflist |refs=...}} or

.... Here we do simple 'find's to make the determination.

It is also possible to do ldr with {{refbegin}} ... {{refend}}

the pattern value is passed to this function but ignored

]]

local function has_ldr (text)

local pattern;

for i, template in ipairs (data.reflist_template_patterns) do

pattern = string.format ('{{%%s*%s[^}]*|%%s*refs%%s*=%%s*[^}|]+', template); -- make a pattern using the selected reflist template

if mw.ustring.find (text, '{{%s*[Rr]eflist[^}]*|%s*refs%s*=%s*[^}|]+') then -- does page use {{Reflist |refs=...}}?

return 'yes'

end

end

if mw.ustring.find (text, '[^<]+') then -- no reflist template, does page use ...?

return 'yes'

else

return 'no';

end

end

--[[--------------------------< H A S _ U S E _ X X X _ D A T E S >--------------------------------------------

returns string set to either of 'dmy' or 'mdy'

TODO: needs companion |cs1-dates= support somehow ... 2 separate tests? one detects {{use xxx dates |cs1-dates=xx}} the other detects {{use xxx dates}}?

Also, detect conflicting |df= parameters?

]]

local global_df;

local function has_use_xxx_dates (text, pattern)

local ret_val = 'no'; -- presume not found

local df_template_patterns = { -- table of redirects to {{Use dmy dates}} and {{Use mdy dates}}

'{{ *[Uu]se (dmy) dates *[|}]', -- 915k -- sorted by approximate transclusion count

'{{ *[Uu]se *(mdy) *dates *[|}]', -- 161k

'{{ *[Uu]se (DMY) dates *[|}]', -- 2929

'{{ *[Uu]se *(dmy) *[|}]', -- 250 + 34

'{{ *([Dd]my) *[|}]', -- 272

'{{ *[Uu]se (MDY) dates *[|}]', -- 173

'{{ *[Uu]se *(mdy) *[|}]', -- 59 + 12

'{{ *([Mm]dy) *[|}]', -- 9

'{{ *[Uu]se (MDY) *[|}]', -- 3

'{{ *([Dd]MY) *[|}]', -- 2

'{{ *([Mm]DY) *[|}]', -- 0

-- '{{ *[Uu]se(mdy) *[|}]',

-- '{{ *[Uu]se(mdy)dates *[|}]',

-- '{{ *[Uu]se(dmy) *[|}]',

}

for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects

local start, _, match = text:find(pattern); -- match is the three letters indicating desired date format

if match then

ret_val = match; -- set return value to the global date format

global_df = match; -- save for |df= tests

text = text:match ('%b{}', start); -- get the whole use xxx dates template

if text:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length

ret_val = ret_val .. ' [' .. text:match ('| *cs1%-dates *= *([lsy][sy]?)') .. ']';

end

break; -- loop escape

end

end

return ret_val;

end

--[[--------------------------< O B J E C T S T A B L E >----------------------------------------------------

Here we define various properties and values necessary to the counting of referencing objects

]]

local objects = {

['unnamed_refs'] = { -- count unnamed ref tags

['func'] = count_pattern, -- the function that does the work for this object

['pattern'] = '()', -- a pattern that the function uses to find and count this object

['count'] = 0, -- the returned result (called count because that is the most common but can be 'yes' or 'no' etc

['label'] = 'unnamed refs' -- a label and markup for displaying the result; used with string.format()

},

['named_refs'] = { -- count named ref tags

['func'] = count_pattern,

['pattern'] = '()',

['count'] = 0,

['label'] = 'named refs'

},

['self_closed_refs'] = { -- count self closed ref tags

['func'] = count_pattern,

['pattern'] = '()',

['count'] = 0,

['label'] = 'self closed'

},

['r_templates'] = { -- count R templates (wrapper for self closed refs)

['func'] = count_pattern,

['pattern'] = '({{%s*[Rr]%s*|)',

['count'] = 0,

['label'] = 'R templates'

},

['refn_templates'] = { -- count Refn templates

['func'] = count_pattern,

['pattern'] = '({{%s*[Rr]efn%s*|)',

['count'] = 0,

['label'] = 'Refn templates'

},

['bare_url_refs'] = { -- count bare url refs

['func'] = count_pattern, -- TODO: separate function to detect protocol relative urls?

['pattern'] = '(]*>%s*http[^<%s]+%s*)',

['count'] = 0,

['label'] = 'bare url refs'

},

['ext_link_refs'] = { -- count unlabeled external link refs

['func'] = count_pattern, -- TODO: separate function to detect protocol relative urls?

['pattern'] = '(]*>%[%s*http[^%]<%s]+%][^<]*)',

['count'] = 0,

['label'] = 'bare ext link refs'

},

['cs1_like_refs'] = { -- count cs1 refs and refs that look like cs1 (cite something)

['func'] = count_cs1_like_refs,

['pattern'] = '(]*>[^<{]*{{%s*[Cc]ite%s+[^|]+)',

['count'] = 0,

['label'] = 'cs1-like refs'

},

['cs1_refs'] = { -- count cs1 refs only

['func'] = count_cs1_refs,

['pattern'] = '(]*>[^<{]*{{%%s*%s%%s*|)', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'cs1 refs'

},

['cs1_like_templates'] = { -- count templates that look like cs1

['func'] = count_cs1_like_templates,

['pattern'] = '({{%s*[Cc]ite%s+[^|]+)',

['count'] = 0,

['label'] = 'cs1-like templates'

},

['cs1_templates'] = { -- count cs1 templates only

['func'] = count_cs1,

['pattern'] = '({{%%s*%s%%f[%%A]%%s*|)', -- will be modified in the func by string.format(); %f to count templates only once: {{cite web|... and {{cite we|...

['count'] = 0,

['label'] = 'cs1 templates'

},

['cs2_refs'] = { -- count cs2 refs

['func'] = count_cs2_refs,

['pattern'] = '(]*>[^<{]*{{%%s*%s%%s*|)', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'cs2 refs'

},

['cs2_templates'] = { -- count cs2 templates

['func'] = count_cs2,

['pattern'] = '{{%%s*%s%%s*|',

['count'] = 0,

['label'] = 'cs2 templates'

},

['vcite_refs'] = { -- count vancite, vcite, and vcite2 refs

-- ['func'] = count_pattern,

-- ['pattern'] = '(]*>[^<{]*{{%s*[Vv]a?n?cite2?%s+[^|]+)',

['func'] = count_vcite_refs,

['pattern'] = '(]*>[^<{]*{{%%s*%s%%s*|)',

['count'] = 0,

['label'] = 'vcite refs'

},

['vcite_templates'] = { -- count vancite templates

['func'] = count_vcite,

['pattern'] = '{{%%s*%s%%s*|',

-- ['func'] = count_pattern,

-- ['pattern'] = '({{%s*[Vv]a?n?cite2?%s+[^|]+)',

['count'] = 0,

['label'] = 'vcite templates'

},

['wikicite_templates'] = { -- count wikicite templates

['func'] = count_pattern,

['pattern'] = '({{%s*[Ww]ikicite%s*|)',

['count'] = 0,

['label'] = 'wikicite templates'

},

['harv_refs'] = { -- count harv refs

['func'] = count_harv_refs,

['pattern'] = '(]*>[^<{]*{{%%s*%s%%s*|)', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'harv refs'

},

['harv_templates'] = { -- count harv templates

['func'] = count_harv,

['pattern'] = '({{%%s*%s%%s*|)',

['count'] = 0,

['label'] = 'harv templates'

},

['sfn_templates'] = { -- count sfn templates

['func'] = count_sfn,

['pattern'] = '({{%%s*%s%%s*|)',

['count'] = 15,

['label'] = 'sfn templates'

},

['rp_templates'] = { -- count rp templates

['func'] = count_rp,

['pattern'] = '({{%%s*%s%%s*[|}])',

['count'] = 0,

['label'] = 'rp templates'

},

['ldr'] = { -- does this article use list defined references?

['func'] = has_ldr,

['pattern'] = '', -- uses multiple patterns which are defined in the function

['count'] = 'no',

['label'] = 'uses ldr'

},

['refbegin_templates'] = { -- count refbegin templates - bibliography lists

['func'] = count_refbegin,

['pattern'] = '({{%%s*%s%%s*[|}])',

['count'] = 0,

['label'] = 'refbegin templates'

},

['cleanup_templates'] = { -- count cleanup templates

['func'] = count_cleanup,

['pattern'] = '({{%%s*%s%%s*[|}])', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'cleanup templates'

},

['dead_link_templates'] = { -- count deadlink templates (includes redirects)

['func'] = count_dead_links,

['pattern'] = '({{%%s*%s%%s*[|}])', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'dead link templates'

},

['webarchive_templates'] = { -- count webarchive templates (includes redirects)

['func'] = count_webarchive,

['pattern'] = '({{%%s*%s%%s*|)', -- will be modified in the func by string.format()

['count'] = 0,

['label'] = 'webarchive templates'

},

['use_xxx_dates'] = { -- does this article use list defined references?

['func'] = has_use_xxx_dates,

['pattern'] = nil, -- uses multiple patterns that are defined in the function

['count'] = 'no',

['label'] = 'use xxx dates'

},

['cs1_dates_df_dmy'] = { -- count

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 df dmy'

},

['cs1_dates_df_mdy'] = { -- count

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 df mdy'

},

['cs1_dates_df_ymd'] = { -- count

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 df ymd'

},

['cs1_dmy_dates'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 dmy dates'

},

['cs1_mdy_dates'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 mdy dates'

},

['cs1_ymd_dates'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 ymd dates'

},

['cs1_dmy_dates_archive'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 dmy archive dates'

},

['cs1_mdy_dates_archive'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 mdy archive dates'

},

['cs1_ymd_dates_archive'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 ymd archive dates'

},

['cs1_dmy_dates_access'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 dmy access dates'

},

['cs1_mdy_dates_access'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 mdy access dates'

},

['cs1_ymd_dates_access'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 ymd access dates'

},

['cs1_last'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 last/first'

},

['cs1_author'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 author'

},

['cs1_authors'] = { -- count cs1 templates only

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 authors'

},

['cs1_vauthors'] = {

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1|2 vauthors'

},

['cs1_mode'] = {

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs1 mode'

},

['cs2_mode'] = {

['func'] = nil, -- handled by cs1_cs2_info_get()

['pattern'] = nil,

['count'] = 0,

['label'] = 'cs2 mode'

},

}

-- here we set the order in which the objects are processed

local teaser_order = {'unnamed_refs', 'named_refs', 'self_closed_refs'} -- for use by {{ref info banner}} to create its 'teaser' when |_teaser=yes

local order = {'unnamed_refs', 'named_refs', 'self_closed_refs', -- these three are always output

'r_templates', -- this and the others only produce output when ...

'refn_templates', -- ... their count is not 0 or not 'no'

'bare_url_refs',

'ext_link_refs',

'cs1_refs',

'cs1_templates',

'cs1_like_refs',

'cs1_like_templates',

'cs2_refs',

'cs2_templates',

'vcite_refs', 'vcite_templates',

'wikicite_templates',

'harv_refs', 'harv_templates',

'sfn_templates',

'rp_templates',

'ldr',

'refbegin_templates',

'cleanup_templates',

'dead_link_templates',

'webarchive_templates',

'use_xxx_dates',

'cs1_dates_df_dmy',

'cs1_dates_df_mdy',

'cs1_dates_df_ymd',

'cs1_dmy_dates',

'cs1_mdy_dates',

'cs1_ymd_dates',

'cs1_dmy_dates_access',

'cs1_mdy_dates_access',

'cs1_ymd_dates_access',

'cs1_dmy_dates_archive',

'cs1_mdy_dates_archive',

'cs1_ymd_dates_archive',

'cs1_last',

'cs1_author',

'cs1_authors',

'cs1_vauthors',

'cs1_mode',

'cs2_mode',

};

--[[--------------------------< R E F _ I N F O >--------------------------------------------------------------

the working part of Template:Ref info

]]

local function ref_info (frame)

local text; -- unparsed page content

local title; -- page title without namespace or interwiki references

local nstitle; -- page title with namespace and interwiki references

local page_title_object; --

local output = {};

local i=1;

local style = frame.args.style or ''; -- styling css for output table

if frame.args[1] then

page_title_object = mw.title.new(frame.args[1]); -- title object for the page specified in the template call

else

page_title_object = mw.title.getCurrentTitle(); -- title object for the current page

end

text = page_title_object:getContent(); -- the unparsed content of the selected page

if nil == text then

return string.format ('{{ref info}} – page is empty or does not exist: %s', frame.args[1] or 'no page');

end

--error (mw.dumpObject (frame:getParent().args))

text = require('Module:Wikitext Parsing').PrepareText(text) -- escape the content of nowiki tags/html comments

nstitle = page_title_object.prefixedText; -- the title of the page (with namespace)

title = page_title_object.text; -- the title of the page (without namespace)

if 'yes' == frame:getParent().args._teaser then

for _, object in ipairs (teaser_order) do -- loop through teaser_order sequence and search for the related objects

if objects[object].func then

objects[object].count = objects[object].func (text, objects[object].pattern, objects) -- do the search and store the result

end

end

objects['named_refs'].count = objects['named_refs'].count - objects['self_closed_refs'].count;

for _, object in ipairs (teaser_order) do -- loop through order and search for the related objects

table.insert (output, string.format ('%s = %s', objects[object].label, objects[object].count));

end

return table.concat (output, '; ');

end

for i, object in ipairs (order) do -- loop through order and search for the related objects

if objects[object].func then

objects[object].count = objects[object].func (text, objects[object].pattern, objects) -- do the search and store the result

end

end

-- for those that count duplicates remove the duplicates from the counts

objects['named_refs'].count = objects['named_refs'].count - objects['self_closed_refs'].count;

table.insert (output, string.format ('

class="wikitable" style="text-align:right; %s"\n|+reference info for %s', style, nstitle, title)); -- output table header

for i, object in ipairs (order) do -- loop through order and search for the related objects

if i<=3 then -- first three (reference tags) are always output

table.insert (output, string.format ('%s\n|%s', objects[object].label, objects[object].count));

elseif 'string' == type (objects[object].count) then -- objects[object].count can be a string or a number

if 'no' ~= objects[object].count then -- if a string and not 'no' ...

table.insert (output, string.format ('%s\n|%s', objects[object].label, objects[object].count)); -- output the result

end

elseif 'number' == type (objects[object].count) then -- if a number ...

if 0 < objects[object].count then -- ... and count is greater than zero ...

table.insert (output, string.format ('%s\n|%s', objects[object].label, objects[object].count)); -- ... output the result

end

end

end

output = {table.concat (output,'\n

\n! scope="row" | ')}; -- concat an intermediate result

table.insert (output, collapsible_tables.cs1); -- add the collapsible tables

table.insert (output, collapsible_tables.cs2);

table.insert (output, collapsible_tables.cs1_like);

table.insert (output, collapsible_tables.vcite);

table.insert (output, collapsible_tables.sfn);

table.insert (output, collapsible_tables.harv);

table.insert (output, '\n

\n|scope="row" colspan="2" style="text-align:center"|explanations\n
\n
');

return table.concat (output);

end

--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------

]]

return {

ref_info = ref_info,

}