Module:Citation/CS1: திருத்தங்களுக்கு இடையிலான வேறுபாடு

உள்ளடக்கம் நீக்கப்பட்டது உள்ளடக்கம் சேர்க்கப்பட்டது
ISSN error detection; Expand uncategorized namespaces; Reg/Sub required msg tweak; Trap coauthors without authors; Hide error messages;
Synch from sandbox; Migrate cite thesis and cite techreport; ISBN & ISSN tweaks; Deprecated parameter tracking; Add date validation;
வரிசை 6:
 
-- Include translation message hooks, ID and error handling configuration settings.
local cfg = mw.loadData( 'Module:Citation/CS1/Configuration/sandbox' );
 
-- Contains a list of all recognized parameters
local whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist/sandbox' );
 
-- Whether variable is set or not
வரிசை 37:
end
return false;
end
 
-- Add this page to the deprecated parameter tracking category
function deprecated_parameter()
if true ~= Page_in_deprecated_cat then -- if we haven't been here before then set a
Page_in_deprecated_cat=true; -- sticky flag so that if there are more than one deprecated parameter the category is added only once
table.insert( z.error_categories, "Pages containing cite templates with deprecated parameters" ); -- add page to category
end
end
 
வரி 307 ⟶ 315:
]]
function issn(id)
local clean_issn;
local issn_copy = id; -- save a copy of unadulterated issn; use this version for display if issn does not validate
local handler = cfg.id_handlers['ISSN'];
local temp = 0;
local text;
local valid_issn = true;
 
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and ndashes from the issn
clean_issn=string.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 ); -- make a copy with a hyphen after 4 digits; use this version for display if issn validates
 
if 8 ~= id:len() or nil == id:match( "^%d*X?$" ) then -- validate the issn: 8 didgits long, containing only 0-9 or X in the last position
valid_issn=false; -- wrong length or improper character
else
id valid_issn= { is_valid_isxn(id:byte(1, 8) }; -- table of individualvalidate bytesissn
for i, v in ipairs( id ) do -- loop through all of the byte an calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X
temp = temp + 10*( 9 - i ); -- it represents 10 decimal
else
temp = temp + tonumber( string.char(v) )*(9-i);
end
end
valid_issn = temp % 11 == 0; -- checksum must be zero for valid issn
end
 
if true == valid_issn then
id = clean_issnstring.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 ); -- if valid, usedisplay thecorrectly cleaned-upformatted version for the display
else
id = issn_copy; -- if not valid, use the show the invalid issn with error message
வரி 347 ⟶ 344:
end
 
-- returns a number according to the month in a date 1 for January, etc. If not a valid month, returns 0
function get_month_number (month)
local long_months = {['january']=1, ['february']=2, ['march']=3, ['april']=4, ['may']=5, ['june']=6, ['july']=7, ['august']=8, ['september']=9, ['october']=10, ['november']=11, ['december']=12};
local short_months = {['jan']=1, ['feb']=2, ['mar']=3, ['apr']=4, ['may']=5, ['jun']=6, ['jul']=7, ['aug']=8, ['sep']=9, ['oct']=10, ['nov']=11, ['dec']=12};
local temp;
temp=long_months[month:lower()];
if temp then return temp; end -- if month is the long-form name
temp=short_months[month:lower()];
if temp then return temp; end -- if month is the short-form name
return 0; -- misspelled or not a month name
end
 
-- returns true if date has one of the five seasons. Else false.
function is_valid_season (season)
if inArray( season, {'winter', 'spring', 'summer', 'fall', 'autumn'} ) then
return true;
end
return false;
end
 
--[[
Returns true if day is less than or equal to the number of days in month; else returns false.
 
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap years before 1582 and Gregorian leap years after 1582.
Where the two calendars overlap (1582 to approximately 1923) dates are assumed to be Gregorian.
]]
function is_valid_date (year, month, day)
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
if (2==month) then -- if February
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0==(year%4) then
month_length = 29;
end
else -- Gregorian calendar
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- date specifies a leap year
month_length = 29; -- if leap year then 29 days in February
end
end
else
month_length=days_in_month[month];
end
 
if tonumber (day) > month_length then
return false;
end
return true;
end
 
--Check a pair of months or seasons to see if both are valid members of a month or season pair.
 
function is_valid_month_season_range(range_start, range_end)
if 0 == get_month_number (range_start:lower()) then -- is this a month range?
if true == is_valid_season (range_start:lower()) then -- not a month range, is this a season range?
return is_valid_season (range_end:lower()); -- range_start is season; return true if range_end also a season; else false
end
return false; -- range_start is not a month or a season
end
if 0 == get_month_number (range_end:lower()) then -- range_start is a month; is range_end also a month?
return false; -- not a month range
end
return true;
end
 
 
--[[
Check date format to see that it is one of the formats approved by MOS:DATE: MMMM D, YYYY; D MMMM YYYY; MMMM YYYY; YYYY-MM-DD; YYYY.
Additionally, check the date to see that it is a real date: no 31 in 30-day months; no 29 February when not a leap year. Months, both long-form and three
character abbreviations, and seasons must be spelled correctly.
 
If the date fails the fomat tests, this function returns false but does not return values for anchor_year and COinS_date. When this happens, the date parameter is
used in the COinS metadata and the CITEREF identifier gets its year from the year parameter if present.
 
Inputs:
date_string - date string from date-holding parameters (date, year, accessdate, embargo, archivedate, etc)
 
Returns:
false if date string is not a real date; else
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is date_string without anchor_year disambiguators if any
]]
function check_date (date_string)
local year;
local month;
local day;
local anchor_year;
local coins_date;
 
if date_string:match("^%d%d%d%d%-%d%d%-%d%d$") then -- Year-initial numerical year month day format
coins_date = date_string:match("%d%d%d%d%-%d%d%-%d%d");
year, month, day=string.match(date_string, "(%d%d%d%d)%-(%d%d)%-(%d%d)");
anchor_year = year;
month=tonumber(month);
if 12 < month or 1 > month then return false; end
 
elseif date_string:match("^%a+%s*%d%d*%s*,%s*%d%d%d%d%a?$") then -- month-initial: month day, year
coins_date = date_string:match("%a+%s*%d%d*%s*,%s*%d%d%d%d");
month, day, anchor_year, year=string.match(date_string, "(%a+)%s*(%d%d*)%s*,%s*((%d%d%d%d)%a?)");
month = get_month_number (month:lower());
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif date_string:match("^%d%d*%s*%a+%s*%d%d%d%d%a?$") then -- date-initial: day month year
coins_date = date_string:match("%d%d*%s*%a+%s*%d%d%d%d");
day, month, anchor_year, year=string.match(date_string, "(%d%d*)%s*(%a+)%s*((%d%d%d%d)%a?)");
month = get_month_number (month:lower());
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
 
elseif mw.ustring.match (date_string, "^%a+%s*[%s%-/–]%s*%a+%s*%d%d%d%d%a?$") then -- month/season range year
local month2
coins_date = mw.ustring.match (date_string, "%a+%s*[%s%-/–]%s*%a+%s*%d%d%d%d");
coins_date= mw.ustring.gsub( coins_date, "–", "-" ); -- replace ndash with hyphen
month, month2, anchor_year, year=mw.ustring.match (date_string, "(%a+)%s*[%s%-/–]%s*(%a+)%s*((%d%d%d%d)%a?)");
day=0; -- mark day as not used
if false == is_valid_month_season_range(month, month2) then
return false;
end
elseif date_string:match("^%a+%s*%d%d%d%d%a?$") then -- month/season year
coins_date = date_string:match("%a+%s*%d%d%d%d");
month, anchor_year, year=string.match(date_string, "(%a+)%s*((%d%d%d%d)%a?)");
day=0; -- mark day as not used
local season=month; -- copy
month = get_month_number (month:lower());
if month == 0 then -- if month text isn't one of the twelve months, might be a season
if false == is_valid_season (season:lower()) then
return false; -- return false not a month or one of the five seasons
end
end
 
elseif date_string:match("^%d%d%d%d?%a?$") then -- year; here accept either YYY or YYYY
coins_date = date_string:match("^%d%d%d%d?");
anchor_year, year=string.match(date_string, "((%d%d%d%d?)%a?)");
month, day = 0, 0; -- mark day and month as not used
else
return false; -- date format not one of the MOS:DATE approved formats
end
 
if 0~=month and 0~=day then -- check year month day dates for validity
if false==is_valid_date(year,month,day) then
return false; -- date string is not a real date return false; unset anchor_year and coins_date
end
end
return true, anchor_year, coins_date; -- format is good and date string represents a real date
end
 
--[[
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns
true and values for anchor_year (used in CITEREF identifiers) and COinS_date (used in the COinS metadata). The |date= parameter test is unique. This function only
accepts anchor_year and COinS_date results from the |date= parameter test and |date= is the only date-holding parameter that is allowed to contain the no-date keywords
"n.d." or "nd" (without quotes).
 
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,
a single error message is created as the dates are tested.
]]
 
function dates(date_parameters_list)
local anchor_year; -- will return as nil if the date being tested is not |date=
local COinS_date; -- will return as nil if the date being tested is not |date=
local error_message ="";
local good_date=false;
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v) then -- if the parameter has a value
if v:match("^c%.%s%d%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
if 'date'==k then
good_date, anchor_year, COinS_date = true, v:match("((c%.%s%d%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter
elseif 'year'==k then
good_date = true;
end
elseif 'year'==k then -- if the parameter is |year= (but not c. year)
if v:match("^%d%d%d%d?%a?$") then -- year with or without CITEREF disambiguator
good_date = true;
end
elseif 'date'==k then -- if the parameter is |date=
if v:match("n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; -- no error when date parameter is set to no date
elseif v:match("nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; -- no error when date parameter is set to no date
else
good_date, anchor_year, COinS_date = check_date (v); -- go test the date
end
else -- any other date-holding parameter
good_date = check_date (v); -- go test the date
end
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "&#124;" .. k .. "="; -- add the failed parameter
end
end
end
if is_set(error_message) then
table.insert( z.message_tail, { seterror( 'bad_date', {error_message}, true ) } ); -- add this error message
end
 
return anchor_year, COinS_date; -- and done
end
 
--[[
வரி 365 ⟶ 563:
function cleanisbn( isbn_str )
return isbn_str:gsub( "[^-0-9X]", "" );
end
 
--[[
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit. If the number is valid the result will be 0.
Before calling this function, issbn/issn must be checked for length and stripped of dashes, spaces and other non-isxn characters.
]]
function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of bytes
len = len+1; -- adjust to be a loop counter
for i, v in ipairs( isxn_str ) do -- loop through all of the byte an calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X
temp = temp + 10*( len - i ); -- it represents 10 decimal
else
temp = temp + tonumber( string.char(v) )*(len-i);
end
end
return temp % 11 == 0; -- returns true if calculation result is zero
end
 
வரி 376 ⟶ 592:
end
local temp = 0;
if len == 10 then
if isbn_str:match( "^%d*X?$" ) == nil then return false; end
return is_valid_isxn(isbn_str = { isbn_str:byte(1, len10) };
for i, v in ipairs( isbn_str ) do
if v == string.byte( "X" ) then
temp = temp + 10*( 11 - i );
else
temp = temp + tonumber( string.char(v) )*(11-i);
end
end
return temp % 11 == 0;
else
local temp = 0;
if isbn_str:match( "^%d*$" ) == nil then return false; end
if isbn_str:match( "^97[89]%d*$" ) == nil then return false; end -- isbn13 begins with 978 or 979
isbn_str = { isbn_str:byte(1, len) };
for i, v in ipairs( isbn_str ) do
வரி 520 ⟶ 728:
Returns empty string if the argument can not be interpreted
as a year.
 
BUG: If editors set |date=n.d or |date=n.da then selectyear() returns the current year for use in CITEREF. These "dates" are caught by dates().
]]
function selectyear( str )
-- Is the input a simple number?
local num = tonumber( str );
if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then
return str;
else
-- Use formatDate to interpret more complicated formats
local lang = mw.getContentLanguage();
local good, result;
good, result = pcall( lang.formatDate, lang, 'Y', str );
if good then return result; end -- if good then
end
return result;
end
else
-- extract year if the date uses seasons
str=string.lower (str);
local seasons={"winter", "spring", "summer", "fall", "autumn"};
local date_string_split=mw.text.split (str, "[%s%-/–]"); -- split date string into parts; white space, hyphen, forward slash, and ndash are allowed separators
local has_season=false;
for n,season_value in ipairs(seasons) do -- for each season ...
for n,split_value in ipairs(date_string_split) do -- ... loop through date string values
if split_value == season_value then -- does the split value match the season value?
if has_season==false then -- found one. if this one is the first we've found ...
has_season=true; -- ... remember that we found a season
end
elseif has_season==true then -- if split_value isn't a season, and we've previously found a season ...
num = tonumber( split_value ); -- ... convert current split value to a number if we can
if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then -- if it's a suitable number
return tostring( num ); -- return it as a string
end -- if num
end -- if string.find
end -- for split value loop
end -- season value loop
end -- if good
end -- if num
end -- selectyear
 
-- Attempts to convert names to initials.
வரி 898 ⟶ 1,085:
local TransChapter = A['TransChapter'];
local TitleType = A['TitleType'];
local Degree = A['Degree'];
local Docket = A['Docket'];
local ArchiveURL = A['ArchiveURL'];
local URL = A['URL']
வரி 967 ⟶ 1,156:
local DoiBroken = A['DoiBroken'];
local ID = A['ID'];
-- Special case for cite techreport.
local ID = A['ID'];
if (config.CitationClass == "techreport") then -- special case for cite techreport
if is_set(Issue) then -- cite techreport uses 'number', which everything else aliases to 'issue'
if not is_set(ID) then -- can we use ID for the "number"?
ID = Issue; -- yes, use it
Issue = ""; -- unset Issue so that "number" isn't duplicated in the rendered citation or COinS metadata
else -- can't use ID so emit error message
ID = ID .. " " .. seterror('redundant_parameters', '<code>&#124;id=</code> and <code>&#124;number=</code>');
end
end
end
local ASINTLD = A['ASINTLD'];
local IgnoreISBN = A['IgnoreISBN'];
வரி 997 ⟶ 1,199:
end
 
local anchor_year; -- used in the CITEREF identifier
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
local COinS_date; -- used in the COinS metadata
 
-- Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates.
-- TODO: 2013-10-27: AirDate is nil when dates() is called because it hasn't been set yet. Move the call to dates() or set AirDate earlier.
anchor_year, COinS_date = dates({['accessdate']=AccessDate, ['airdate']=AirDate, ['archivedate']=ArchiveDate, ['date']=Date, ['doi_brokendate']=DoiBroken,
['embargo']=Embargo, ['laydate']=LayDate, ['publicationdate']=PublicationDate, ['year']=Year});
 
if not is_set(Year) then -- prevent Year from being set from DateIn TODO: eliminate the need for this?
if is_set(anchor_year) then
Year = anchor_year;
end
end
 
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
-- Account for the oddity that is {{cite conference}}, before generation of COinS data.
வரி 1,044 ⟶ 1,260:
['Title'] = Title,
['PublicationPlace'] = PublicationPlace,
['Date'] = first_set(COinS_date, Date, Year, PublicationDate),
['Series'] = Series,
['Volume'] = Volume,
வரி 1,092 ⟶ 1,308:
control.lastauthoramp = nil;
control.maximum = #a + 1;
deprecated_parameter(); -- |coauthor= and |coathors= are deprecated; add this page to deprecated parameter category
end
வரி 1,099 ⟶ 1,316:
if not is_set(Authors) and is_set(Coauthors) then -- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specified
table.insert( z.message_tail, { seterror('coauthors_missing_author', {}, true) } ); -- emit error message
deprecated_parameter(); -- |coauthor= and |coathors= are deprecated; add this page to deprecated parameter category
end
 
வரி 1,146 ⟶ 1,364:
if is_set(Date) then
local Month = A['Month'];
if is_set(Month) then
deprecated_parameter(); -- |month= (and also |day=) is deprecated; add this page to deprecated parameter category
Date = Month .. " " .. Date;
local Day = A['Day']
வரி 1,394 ⟶ 1,613:
end
 
Others = is_set(Others) and (sepc .. " " .. Others) or "";
 
TitleType = is_set(TitleType) and (" (" .. TitleType .. ")") or "";
-- handle type parameter for those CS1 citations that have default values
TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or "";
 
if "pressrelease" == config.CitationClass then -- if this citation is cite press release
if not is_set (TitleType) then
TitleType = "Press release"; -- if type not specified, display the press release annotation
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed
end
 
elseif "techreport" == config.CitationClass then -- if this citation is cite techreport
if not is_set (TitleType) then
TitleType = "Technical report"; -- if type not specified, display the techreport annotation
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed; |number=, if set, will be displayed
end
elseif "thesis" == config.CitationClass then -- if this citation is cite thesis
if not is_set (TitleType) then
if is_set(Degree) then -- if type not specified, display one of the thesis annotations
TitleType = Degree .. " thesis"; -- if a degree (masters, PhD, ...) is specified include it in the display
else
TitleType = "Thesis"; -- otherwise display the simple thesis annotation
end
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed
end
end
if is_set(TitleType) then -- if type parameter is specified
TitleType = " (" .. TitleType .. ")"; -- display it in parentheses
end
 
TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or "";
Edition = is_set(Edition) and (" " .. wrap( 'edition', Edition )) or "";
Issue = is_set(Issue) and (" (" .. Issue .. ")") or "";
வரி 1,434 ⟶ 1,684:
if is_set(ID) then ID = sepc .." ".. ID; end
if "thesis" == config.CitationClass and is_set(Docket) then
ID = sepc .." Docket ".. Docket .. ID;
end
 
ID_list = buildidlist( ID_list, {DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo} );
வரி 1,680 ⟶ 1,934:
end
end
names[ #names + 1 ] = Year or anchor_year; -- Year first for legacy citations
id = anchorid(names)
end
"https://tamilar.wiki/w/Module:Citation/CS1" இலிருந்து மீள்விக்கப்பட்டது