Jump to content

Module:Citation/CS1/Identifiers and Holidays: Difference between pages

(Difference between pages)
17,025 bytes removed ,  1 year ago
m
no edit summary
m>Trappist the monk
No edit summary
 
imported>TXJ
mNo edit summary
 
Line 1: Line 1:
--[[
{{Incomplete}}
History of changes since last sync: 2015-12-12
The days in the below table are commonly observed holidays, memorial days, days of awareness, and otherwise important days for people who are [[transgender]], [[genderqueer]], [[nonbinary]], [[intersex]], or [[gender-variant identities worldwide|members of traditional gender identities that do not fit into the Western gender binary]].
{| class="wikitable sortable"
!Name
!Date
!Region
!Description
|-
|Trans Prisoner Day of Action and Solidarity
|22nd January
|International<ref>https://transprisoners.net/about/</ref>
|
|-
|National Transition Week
|The last full week (Monday - Friday) in January
|First observed on January 24th-28th of 2022<ref>{{Cite web |title=National Transition Week |date= |access-date=9 July 2022 |url= https://nationaltransitionweek.wordpress.com/}}</ref>
|-
|LGBT History Month
|February
|UK<ref>[https://lgbthistorymonth.org.uk/about https://lgbthistorymonth.org.uk/]</ref>, Hungary<ref>http://www.lmbttortenetihonap.hu/</ref>
|
|-
|Femminiello Pride<ref name="RoadsAndKingdoms">Danielle Oteri. "Femminiello Pride." ''Roads and Kingdoms'' (magazine). December 30, 2015. Retrieved July 28, 2020. https://roadsandkingdoms.com/2015/femminiello-pride/</ref>
|2nd February
|Montevergine, Italy
|Since the thirteenth century CE, the Catholic festival of Candlemas on February 2 also honors the [[gender-variant identities worldwide#femminiello|femminiello]], a traditional gender-variant role in Italy. Pilgrims make their way to the remote mountain church at Motevergine, whose icon, the Madonna of Transformation, Mamma Schiavona, is said to have miraculously saved the lives of victims of homophobic violence in 1256 CE. The festival is celebrated with the long and energetic tammurriata dance, and a candle-lit procession, by pilgrims who are visibly gender nonconforming. Historically, this has been called ''juta dei femminielli.'' Since 2002, it has also been called Femminiello Pride.<ref name="femminiello huffpost">Giuseppe Melillo. "Una storia antica: Napoli, i femminielli e la figliata." ''Huffington Post'' (magazine). January 24, 2018. Retrieved July 28, 2020.  https://www.huffingtonpost.it/giuseppe-melillo/una-storia-antica-napoli-i-femminielli-e-la-figliata_a_23339374/</ref><ref name="RoadsAndKingdoms" />
|-
|[[Transmasculine]] Visibility Day/Transmasculine Pride and Visibility Day
|20th February
|
|Established to commemorate the ENAHT (Encontro Nacional de Homens Trans, "National Meeting of Trans Men") organized by Ibrat (Instituto Brasileiro de Transmaculinidades, "Brazilian Institute of Transmaculinities") which took place on 20 February 2015.<ref>https://www.facebook.com/festivaltransarte/posts/1433114963780391</ref><ref>https://www.facebook.com/gaavahbrasil/posts/pfbid0UMwZnrrrwJ9uRkrwrgcrmYf6GCMGKaRBqf78B2jRgHiEFhppYSvaFys1qPWdZx95l</ref>
|-
|''Dies Sanguinis'' (Day of Blood)
|24th March
|Originating in Phrygia (where Turkey is today), spreading across the ancient Roman empire, as far as Roman London
|From 2,300 years ago to the 6th century CE, this was celebrated by the gender-variant [[gender-variant identities worldwide#Gallae|Gallae]] priests of the goddess Cybele and the god Attis. The Day of Blood was celebrated by dancing around a felled and decorated pine tree, symbolizing the death and rebirth of Attis. As part of this ritual, any new Gallae initiates would voluntarily castrate themselves, as part of transitioning to a feminine appearance.<ref name="kaldera 174">Raven Kaldera. ''Hermaphrodeities: The Transgender Spirituality Workbook.'' Hubbardston, Massachusetts: Asphodel Press, 2008. P. 174-179.</ref><ref name="seabrook gallae about">Laura Anne Seabrook, "About this comic." ''Tales of the Gallae.'' http://totg-mirror.thecomicseries.com/about/</ref>
|-
|Trans Day of Visibility
|31st March
|International<ref>http://www.transstudent.org/tdov</ref>
|
|-
|Day of Silence
|Various days in April
|
|A student-led observance to take a day-long vow of silence in protest of the harassment and discrimination of LGBTQ+ people in schools.<ref>{{Cite web|url=https://www.glsen.org/day-of-silence|title=Join Us for Day of Silence on April 23, 2021 and Support LGBTQ Students!|website=GLSEN|language=en|access-date=2021-10-15}}</ref>
|-
|Nonbinary Parents Day
|3rd Sunday in April
|
|Created by educator and nonbinary parent Johnny Blazes.<ref name="fami_Cele">{{Cite web |title=Celebrating Nonbinary Parents Day with Parent & Educator Johnny Blazes |author= |work=Family Equality |date=16 April 2021 |access-date=3 May 2021 |url= https://www.familyequality.org/2021/04/16/celebrating-nonbinary-parents-day-with-founder-johnny-blazes/}}</ref>
|-
| [[Xenogender]] Visibility Day
| 15th May
| International
| First celebrated in 2021.<ref name="redd_r/Xe">{{Cite web |title=Happy Xenogender Visibility Day! |author=Great_White_Wrym |work=reddit - r/XenogendersAndMore |date=15 May 2021 |access-date=22 June 2021 |url= https://www.reddit.com/r/XenogendersAndMore/comments/nd5ycb/happy_xenogender_visibility_day/}}</ref><ref>{{cite tweet|user=lotusflwrbunny |number=1393693536588025858 |date=15 May 2021 |title=apparently it’s the first xenogender visibility day ever so qrt with ur xenogenders!!}} </ref>
|-
|International Day Against Homophobia, Transphobia and Biphobia
|17th May
|International<ref>https://may17.org/</ref>
|
|-
|[[Agender]] Pride Day
|19th May<ref>{{Cite web |title=Important LGBT Dates |author= |work=LGBTLifeWestchester.org |date= |access-date=11 November 2021 |url= https://www.lgbtlifewestchester.org/important_lgbt_dates}}</ref><ref>{{Cite web |title=Agender Pride Day |last=Ohene |first=Benjamin |work=Believe Out Loud |date= |access-date=11 November 2021 |url= https://www.believeoutloud.com/voices/article/agender-pride-day/}}</ref>
|
|
|-
|LGBT History Month
|June
|Italy<ref>https://en.wikipedia.org/wiki/LGBT_History_Month#In_Italy</ref>
|
|-
|Queer History Month
|June
|Berlin<ref>http://queerhistory.de/</ref>
|
|-
|[[International Nonbinary Day]]
|14th July
|International<ref>https://femmesblackmarket.wordpress.com/2012/03/08/calling-for-an-international-non-binary-gender-day/</ref>
|
|-
|LGBT History Month
|October
|USA<ref>https://en.wikipedia.org/wiki/LGBT_History_Month#In_the_United_States</ref>
|
|-
|National Nonbinary Kids Day
|1st October
|USA
|First observed in 2021, started by PFLAG Jacksonville & Professor Sex.<ref>{{cite web|url=https://www.instagram.com/p/CUd1r38tG4G/ |title=PFLAG of Jacksonville and Professor Sex are excited to announce tomorrow October 1, 2021 is the first National Nonbinary Kids Day! |work=Instagram |date=30 September 2021}}</ref>
|-
|National Coming Out Day
|11th October
|USA<ref>https://www.hrc.org/resources/national-coming-out-day</ref>, International
|"National Coming Out Day was created in 1988 to commemorate the 1987 March on Washington for Gay and Lesbian Rights, which reportedly drew over 200,000 protesters to the nation's capital that Oct. 11."<ref name="Lavietes">{{Cite web |title=National Coming Out Day: 21 people who have come out in 2021 |last=Lavietes |first=Matt |work=NBC News |date=11 October 2021 |access-date=15 October 2021 |url= https://www.nbcnews.com/nbc-out/nbc-out-proud/national-coming-day-21-people-come-2021-rcna2839}}</ref>
|-
|[https://cassolotl.tumblr.com/post/166404257550 Cake for Trans Friends Day, or Trans Cake Day]
|14th October
|International<ref name="cassolotl_cake_tumblr">October 14, 2017. https://cassolotl.tumblr.com/post/166404257550</ref><ref>https://cybre.space/@cassolotl/98826563853949635</ref>
|Established by cassolotl in 2017, who wrote that in response to how most days about trans people "involve marginalised people doing yet more work to draw attention to themselves in a dangerous environment [...] Those days can be (and always are, for me) scary and sad. [...] So I declared [this] the first annual Cake For Trans Friends Day. I ended up shortening it to Trans Cake Day [...] Basically, instead of us doing all the work, people (especially cis people, I feel!) give cake to their trans friends and family to show them how appreciated they are. There’s so much anger and violence surrounding trans people, but I think we should be celebrated and loved. [...] a bit like Mother’s Day - a birthday for every trans person to celebrate together at the same time, and be showered with goodness by people who care about us."<ref name="cassolotl_cake_tumblr" />
|-
|[[International Pronouns Day]]
|3rd Wednesday of October
|International<ref name="pronounsday_faq">https://pronounsday.org/faqs</ref>
|Established in 2018.<ref name="pronounsday_faq" /> Ways to participate include using the #PronounsDay hashtag, telling about your pronouns on social media and on name badges, distributing leaflets, setting up a photo booth in public for people to take selfies with their pronouns, and other efforts to creatively raise awareness.<ref>https://pronounsday.org/participating</ref>
|-
|[[Genderfluid]] Visibility Week
|Third full week of October
|International
|First observed from Oct 17-24 of 2021.<ref>{{Cite web |title=LGBTQIA Awareness Dates |author= |work=On Trend Shirts |date= |access-date=4 September 2022 |url= https://ontrendshirts.com/pages/lgbtqia-awareness-dates}}</ref> The dates for 2022 will be October 16-22.<ref>{{cite web |access-date=4 September 2022 |title= Prideraiser Awareness Observances|url=https://www.prideraiser.org/awareness-calendar/}}</ref>
|-
|[[Intersex]] Awareness Day
|26th October
|International<ref>https://intersexday.org/</ref>
|Started in 2003 by Betsy Driver and Emi Koyama.<ref>{{Cite web |title=The origins of Intersex Awareness Day |last=Driver |first=Betsy |work=Intersex Day |date=14 October 2015 |access-date=15 October 2021 |url= https://intersexday.org/en/origin-intersex-awareness-day/}}</ref> October 26 is the anniversary of a protest that took place in Boston by the Intersex Society of North America.<ref>{{Cite web |title=When Max Beck and Morgan Holmes went to Boston |last=Holmes |first=Morgan |work=Intersex Day |date=17 October 2015 |access-date=15 October 2021 |url= https://intersexday.org/en/max-beck-morgan-holmes-boston-1996/}}</ref>
|-
|Trans Parent Day
|1st Sunday in November
|USA<ref>http://www.transparentday.org/</ref>
|Established in 2009 to celebrate "the love between transgender parents and their children and transgender children and their parents".<ref>{{Cite web |title=TransParent Day 2014 |author= |work=Transgender Law Center |date=3 November 2014 |access-date=8 November 2021 |url= https://transgenderlawcenter.org/archives/11184}}</ref>
|-
|Intersex Day of Solidarity ''or'' Intersex Day of Remembrance
|8th November
|
|This date was the birthday of Herculine Barbin (also variously known as Alexina Barbin or Abel Barbin), a French intersex person whose memoirs were later published by the philosopher Michel Foucault. The event was first celebrated in 2005.<ref>{{Cite web |title=Intersex Day of Solidarity |work=Intersex Day |date=30 May 2011 |access-date=15 October 2021 |url= https://intersexday.org/en/intersex-day-of-solidarity/}}</ref>
|-
|Transgender Awareness Week
|13th - 19th November
|USA<ref>https://www.glaad.org/transweek</ref>
|
|-
|[https://trans-rite.tumblr.com/ Transgender Rite of Ancestor Elevation]
|12 - 20 November
|International<ref name="trans-rite-faq">"The Transgender Rite of Ancestor Elevation: FAQ." November 11, 2017. ''Transgender Rite of Ancestor Elevation.'' https://trans-rite.tumblr.com/post/167382057159/the-transgender-rite-of-ancestor-elevation-faq</ref>
|A 9-day non-denominational ritual ending with the Trans Day of Remembrance, honoring the spirits of trans people past and future. Each night, participants add a book to a stack on the floor, with a cup of water and a candle, forming a memorial altar that rises taller each night. Established 2014.<ref name="trans-rite-faq" />
|-
|Trans Day of Remembrance
|20th November
|International<ref>https://tdor.info/about-2/</ref>
|
|-
|Gender Expansive Parents' Day
|6th December
|Official holiday in North Carolina, USA<ref name="news_Aday">{{Cite web |title=A day to celebrate all parents, including LGBTQ parents, in NC |last=Vaughan |first=Dawn Baumgartner |work=The News & Observer |date=4 December 2020 |access-date=4 January 2021 |url= https://www.newsobserver.com/news/politics-government/article247605375.html}}</ref>
|Formally created in 2020
|-
|[[Demigender]]s Awareness and Pride Day
|15th December
|
|Created in 2021 by bluebolt712 to raise awareness about demigenders.<ref>{{cite web |url=https://www.instagram.com/p/CXgI9g6umH1/ |author=Bluebolt712 |date= 15 December 2021|access-date=15 December 2021 |title=(Post 1/4) Today is Demigenders Awareness and Pride Day. This is a day I created because I noticed the sharp increase in the number of people claiming these labels as their own in the past few years. Yet, the awareness of demigenders remains quite low.}}</ref><ref>{{Cite web |title=Demigenders Resources |author=Bluebolt712 |work=Bluebolt712's LGBT+ Resources |date= |access-date=15 December 2021 |url= https://bluebolt712.wordpress.com/demigenders-resources/}}</ref>
|-
|[[IAmNonbinary]]
|date varies each year
|International
|Observed by using the #IAmNonbinary hashtag on social media.
|}


2015-12-16: add support for eissn;
==See also==
* [[History of nonbinary gender]]
* [[Gender variance in spirituality]]


]]
== References ==
<references/>


local identifiers = {};
[[Category:Celebrations]]


 
[[de:feier-_aktions-_und_gedenktage]]
--[[--------------------------< F O R W A R D  D E C L A R A T I O N S >--------------------------------------
]]
 
local is_set, in_array, set_error, select_one, add_maint_cat; -- functions in Module:Citation/CS1/Utilities
 
local z; -- table of tables defined in Module:Citation/CS1/Utilities
 
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
 
 
--[[--------------------------< E X T E R N A L _ L I N K _ I D >----------------------------------------------
 
Formats a wiki style external link
 
]]
 
local function external_link_id(options)
local url_string = options.id;
if options.encode == true or options.encode == nil then
url_string = mw.uri.encode( url_string );
end
return mw.ustring.format( '[[%s|%s]]%s[%s%s%s %s]',
options.link, options.label, options.separator or "&nbsp;",
options.prefix, url_string, options.suffix or "",
mw.text.nowiki(options.id)
);
end
 
 
--[[--------------------------< I N T E R N A L _ L I N K _ I D >----------------------------------------------
 
Formats a wiki style internal link
 
]]
 
local function internal_link_id(options)
return mw.ustring.format( '[[%s|%s]]%s[[%s%s%s|%s]]',
options.link, options.label, options.separator or "&nbsp;",
options.prefix, options.id, options.suffix or "",
mw.text.nowiki(options.id)
);
end
 
 
--[[--------------------------< IS _ V A L I D _ I S X N >-----------------------------------------------------
 
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit.
ISBN-13 is checked in check_isbn().
 
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.
 
]]
 
local function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9'  → 0x39, 'X' → 0x58
len = len+1; -- adjust to be a loop counter
for i, v in ipairs( isxn_str ) do -- loop through all of the bytes and calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58)
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
 
 
--[[--------------------------< IS _ V A L I D _ I S X N  _ 1 3 >----------------------------------------------
 
ISBN-13 and ISMN validator code calculates checksum across all 13 isbn/ismn digits including the check digit.
If the number is valid, the result will be 0. Before calling this function, isbn-13/ismn must be checked for length
and stripped of dashes, spaces and other non-isxn-13 characters.
 
]]
 
local function is_valid_isxn_13 (isxn_str)
local temp=0;
isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9'  → 0x39
for i, v in ipairs( isxn_str ) do
temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit
end
return temp % 10 == 0; -- sum modulo 10 is zero when isbn-13/ismn is correct
end
 
 
--[[--------------------------< C H E C K _ I S B N >------------------------------------------------------------
 
Determines whether an ISBN string is valid
 
]]
 
local function check_isbn( isbn_str )
if nil ~= isbn_str:match("[^%s-0-9X]") then return false; end -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
isbn_str = isbn_str:gsub( "-", "" ):gsub( " ", "" ); -- remove hyphens and spaces
local len = isbn_str:len();
if len ~= 10 and len ~= 13 then
return false;
end
 
if len == 10 then
if isbn_str:match( "^%d*X?$" ) == nil then return false; end
return is_valid_isxn(isbn_str, 10);
else
local temp = 0;
if isbn_str:match( "^97[89]%d*$" ) == nil then return false; end -- isbn13 begins with 978 or 979; ismn begins with 979
return is_valid_isxn_13 (isbn_str);
end
end
 
 
--[[--------------------------< I S M N >----------------------------------------------------------------------
 
Determines whether an ISMN string is valid.  Similar to isbn-13, ismn is 13 digits begining 979-0-... and uses the
same check digit calculations.  See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf
section 2, pages 9–12.
 
]]
 
local function ismn (id)
local handler = cfg.id_handlers['ISMN'];
local text;
local valid_ismn = true;
 
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the ismn
 
if 13 ~= id:len() or id:match( "^9790%d*$" ) == nil then -- ismn must be 13 digits and begin 9790
valid_ismn = false;
else
valid_ismn=is_valid_isxn_13 (id); -- validate ismn
end
 
-- text = internal_link_id({link = handler.link, label = handler.label, -- use this (or external version) when there is some place to link to
-- prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
text="[[" .. handler.link .. "|" .. handler.label .. "]]" .. handler.separator .. id; -- because no place to link to yet
 
if false == valid_ismn then
text = text .. ' ' .. set_error( 'bad_ismn' ) -- add an error message if the ismn is invalid
end
return text;
end
 
 
--[[--------------------------< I S S N >----------------------------------------------------------------------
 
Validate and format an issn.  This code fixes the case where an editor has included an ISSN in the citation but
has separated the two groups of four digits with a space.  When that condition occurred, the resulting link looked
like this:
 
|issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327]  -- can't have spaces in an external link
This code now prevents that by inserting a hyphen at the issn midpoint.  It also validates the issn for length
and makes sure that the checkdigit agrees with the calculated value.  Incorrect length (8 digits), characters
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check issn error message.  The
issn is always displayed with a hyphen, even if the issn was given as a single group of 8 digits.
 
]]
 
local function issn(id, e)
local issn_copy = id; -- save a copy of unadulterated issn; use this version for display if issn does not validate
local handler;
local text;
local valid_issn = true;
if e then
handler = cfg.id_handlers['EISSN'];
else
handler = cfg.id_handlers['ISSN'];
end
 
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the issn
 
if 8 ~= id:len() or nil == id:match( "^%d*X?$" ) then -- validate the issn: 8 digits long, containing only 0-9 or X in the last position
valid_issn=false; -- wrong length or improper character
else
valid_issn=is_valid_isxn(id, 8); -- validate issn
end
 
if true == valid_issn then
id = string.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 ); -- if valid, display correctly formatted version
else
id = issn_copy; -- if not valid, use the show the invalid issn with error message
end
text = external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if false == valid_issn then
text = text .. ' ' .. set_error( 'bad_issn', e and 'e' or '' ) -- add an error message if the issn is invalid
end
return text
end
 
 
--[[--------------------------< A M A Z O N >------------------------------------------------------------------
 
Formats a link to Amazon.  Do simple error checking: asin must be mix of 10 numeric or uppercase alpha
characters.  If a mix, first character must be uppercase alpha; if all numeric, asins must be 10-digit
isbn. If 10-digit isbn, add a maintenance category so a bot or awb script can replace |asin= with |isbn=.
Error message if not 10 characters, if not isbn10, if mixed and first character is a digit.
 
]]
 
local function amazon(id, domain)
local err_cat = ""
 
if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then
err_cat =  ' ' .. set_error ('bad_asin'); -- asin is not a mix of 10 uppercase alpha and numeric characters
else
if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X)
if check_isbn( id ) then -- see if asin value is isbn10
add_maint_cat ('ASIN');
elseif not is_set (err_cat) then
err_cat =  ' ' .. set_error ('bad_asin'); -- asin is not isbn10
end
elseif not id:match("^%u[%d%u]+$") then
err_cat =  ' ' .. set_error ('bad_asin'); -- asin doesn't begin with uppercase alpha
end
end
if not is_set(domain) then
domain = "com";
elseif in_array (domain, {'jp', 'uk'}) then -- Japan, United Kingdom
domain = "co." .. domain;
elseif in_array (domain, {'au', 'br', 'mx'}) then -- Australia, Brazil, Mexico
domain = "com." .. domain;
end
local handler = cfg.id_handlers['ASIN'];
return external_link_id({link=handler.link,
label=handler.label, prefix=handler.prefix .. domain .. "/dp/",
id=id, encode=handler.encode, separator = handler.separator}) .. err_cat;
end
 
 
--[[--------------------------< A R X I V >--------------------------------------------------------------------
 
See: http://arxiv.org/help/arxiv_identifier
 
format and error check arXiv identifier.  There are three valid forms of the identifier:
the first form, valid only between date codes 9108 and 0703 is:
arXiv:<archive>.<class>/<date code><number><version>
where:
<archive> is a string of alpha characters - may be hyphenated; no other punctuation
<class> is a string of alpha characters - may be hyphenated; no other punctuation
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
first digit of YY for this form can only 9 and 0
<number> is a three-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)
the second form, valid from April 2007 through December 2014 is:
arXiv:<date code>.<number><version>
where:
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
<number> is a four-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces
 
the third form, valid from January 2015 is:
arXiv:<date code>.<number><version>
where:
<date code> and <version> are as defined for 0704-1412
<number> is a five-digit number
]]
 
local function arxiv (id, class)
local handler = cfg.id_handlers['ARXIV'];
local year, month, version;
local err_cat = '';
local text;
if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9108-0703 format w/ & w/o version
year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month
((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok?
err_cat = ' ' .. set_error( 'bad_arxiv' ); -- set error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years)
((7 == year) and (4 > month)) then --or -- when year is 07, is month invalid (before April)?
err_cat = ' ' .. set_error( 'bad_arxiv' ); -- set error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years)
err_cat = ' ' .. set_error( 'bad_arxiv' ); -- set error message
end
else
err_cat = ' ' .. set_error( 'bad_arxiv' ); -- arXiv id doesn't match any format
end
 
text = external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
 
if is_set (class) then
class = ' [[' .. '//arxiv.org/archive/' .. class .. ' ' .. class .. ']]'; -- external link within square brackets, not wikilink
else
class = ''; -- empty string for concatenation
end
return text .. class;
end
 
 
--[[--------------------------< N O R M A L I Z E _ L C C N >--------------------------------------------------
 
lccn normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization)
1. Remove all blanks.
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.
3. If there is a hyphen in the string:
a. Remove it.
b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):
1. All these characters should be digits, and there should be six or less. (not done in this function)
2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.
 
Returns a normalized lccn for lccn() to validate.  There is no error checking (step 3.b.1) performed in this function.
]]
 
local function normalize_lccn (lccn)
lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace
 
if nil ~= string.find (lccn,'/') then
lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it
end
 
local prefix
local suffix
prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix
 
if nil ~= suffix then -- if there was a hyphen
suffix=string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6
lccn=prefix..suffix; -- reassemble the lccn
end
return lccn;
end
 
 
--[[--------------------------< L C C N >----------------------------------------------------------------------
 
Format LCCN link and do simple error checking.  LCCN is a character string 8-12 characters long. The length of
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.
http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:lccn/
 
length = 8 then all digits
length = 9 then lccn[1] is lower case alpha
length = 10 then lccn[1] and lccn[2] are both lower case alpha or both digits
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lower case alpha or both digits
length = 12 then lccn[1] and lccn[2] are both lower case alpha
 
]]
 
local function lccn(lccn)
local handler = cfg.id_handlers['LCCN'];
local err_cat =  ''; -- presume that LCCN is valid
local id = lccn; -- local copy of the lccn
 
id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes)
local len = id:len(); -- get the length of the lccn
 
if 8 == len then
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits)
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 9 == len then -- LCCN should be adddddddd
if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern?
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ...
if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
end
elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd
if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
elseif 12 == len then -- LCCN should be aadddddddddd
if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
else
err_cat = ' ' .. set_error( 'bad_lccn' ); -- wrong length, set an error message
end
 
if not is_set (err_cat) and nil ~= lccn:find ('%s') then
err_cat = ' ' .. set_error( 'bad_lccn' ); -- lccn contains a space, set an error message
end
 
return external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=lccn,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
 
 
--[[--------------------------< P M I D >----------------------------------------------------------------------
 
Format PMID and do simple error checking.  PMIDs are sequential numbers beginning at 1 and counting up.  This
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable
test_limit will need to be updated periodically as more PMIDs are issued.
 
]]
 
local function pmid(id)
local test_limit = 30000000; -- update this value as PMIDs approach
local handler = cfg.id_handlers['PMID'];
local err_cat =  ''; -- presume that PMID is valid
if id:match("[^%d]") then -- if PMID has anything but digits
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
else -- PMID is only digits
local id_num = tonumber(id); -- convert id to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMID is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
end
end
return external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
 
 
--[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------
 
Determines if a PMC identifier's online version is embargoed. Compares the date in |embargo= against today's date.  If embargo date is
in the future, returns the content of |embargo=; otherwise, returns and empty string because the embargo has expired or because
|embargo= was not set in this cite.
 
]]
 
local function is_embargoed (embargo)
if is_set (embargo) then
local lang = mw.getContentLanguage();
local good1, embargo_date, good2, todays_date;
good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );
good2, todays_date = pcall( lang.formatDate, lang, 'U' );
if good1 and good2 then -- if embargo date and today's date are good dates
if tonumber( embargo_date ) >= tonumber( todays_date ) then -- is embargo date is in the future?
return embargo; -- still embargoed
else
add_maint_cat ('embargo')
return ''; -- unset because embargo has expired
end
end
end
return ''; -- |embargo= not set return empty string
end
 
 
--[[--------------------------< P M C >------------------------------------------------------------------------
 
Format a PMC, do simple error checking, and check for embargoed articles.
 
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not
be linked to the article.  If the embargo date is today or in the past, or if it is empty or omitted, then the
PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
 
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation
has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link.  Function is_embargoed ()
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.
 
PMCs are sequential numbers beginning at 1 and counting up.  This code checks the PMC to see that it contains only digits and is less
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.
 
]]
 
local function pmc(id, embargo)
local test_limit = 5000000; -- update this value as PMCs approach
local handler = cfg.id_handlers['PMC'];
local err_cat =  ''; -- presume that PMC is valid
local text;
 
if id:match("[^%d]") then -- if PMC has anything but digits
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
else -- PMC is only digits
local id_num = tonumber(id); -- convert id to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMC is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
end
end
if is_set (embargo) then -- is PMC is still embargoed?
text="[[" .. handler.link .. "|" .. handler.label .. "]]:" .. handler.separator .. id .. err_cat; -- still embargoed so no external link
else
text = external_link_id({link = handler.link, label = handler.label, -- no embargo date or embargo has expired, ok to link to article
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
return text;
end
 
 
--[[--------------------------< D O I >------------------------------------------------------------------------
 
Formats a DOI and checks for DOI errors.
 
DOI names contain two parts: prefix and suffix separated by a forward slash.
Prefix: directory indicator '10.' followed by a registrant code
Suffix: character string of any length chosen by the registrant
 
This function checks a DOI name for: prefix/suffix.  If the doi name contains spaces or endashes, or, if it ends
with a period or a comma, this function will emit a bad_doi error message.
 
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in doi names.
 
]]
 
local function doi(id, inactive)
local cat = ""
local handler = cfg.id_handlers['DOI'];
local text;
if is_set(inactive) then
local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date
text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id;
if is_set(inactive_year) then
table.insert( z.error_categories, "Pages with DOIs inactive since " .. inactive_year );
else
table.insert( z.error_categories, "Pages with inactive DOIs" ); -- when inactive doesn't contain a recognizable year
end
inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"
else
text = external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
inactive = ""
end
 
if nil == id:match("^10%.[^%s–]-/[^%s–]-[^%.,]$") then -- doi must begin with '10.', must contain a fwd slash, must not contain spaces or endashes, and must not end with period or comma
cat = ' ' .. set_error( 'bad_doi' );
end
return text .. inactive .. cat
end
 
 
--[[--------------------------< O P E N L I B R A R Y >--------------------------------------------------------
 
Formats an OpenLibrary link, and checks for associated errors.
 
]]
 
local function openlibrary(id)
local code = id:match("^%d+([AMW])$"); -- only digits followed by 'A', 'M', or 'W'
local handler = cfg.id_handlers['OL'];
 
if ( code == "A" ) then
return external_link_id({link=handler.link, label=handler.label,
prefix=handler.prefix .. 'authors/OL',
id=id, separator=handler.separator, encode = handler.encode})
elseif ( code == "M" ) then
return external_link_id({link=handler.link, label=handler.label,
prefix=handler.prefix .. 'books/OL',
id=id, separator=handler.separator, encode = handler.encode})
elseif ( code == "W" ) then
return external_link_id({link=handler.link, label=handler.label,
prefix=handler.prefix .. 'works/OL',
id=id, separator=handler.separator, encode = handler.encode})
else
return external_link_id({link=handler.link, label=handler.label,
prefix=handler.prefix .. 'OL',
id=id, separator=handler.separator, encode = handler.encode}) .. ' ' .. set_error( 'bad_ol' );
end
end
 
 
--[[--------------------------< M E S S A G E _ I D >----------------------------------------------------------
 
Validate and format a usenet message id.  Simple error checking, looks for 'id-left@id-right' not enclosed in
'<' and/or '>' angle brackets.
 
]]
 
local function message_id (id)
local handler = cfg.id_handlers['USENETID'];
 
local text = external_link_id({link = handler.link, label = handler.label,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$')then -- doesn't have '@' or has one or first or last character is '< or '>'
text = text .. ' ' .. set_error( 'bad_message_id' ) -- add an error message if the message id is invalid
end
return text
end
 
 
--[[--------------------------< B U I L D _ I D _ L I S T >--------------------------------------------------------
 
Takes a table of IDs created by extract_ids() and turns it into a table of formatted ID outputs.
 
inputs:
id_list – table of identifiers built by extract_ids()
options – table of various template parameter values used to modify some manually handled identifiers
 
]]
 
local function build_id_list( id_list, options )
local new_list, handler = {};
 
local function fallback(k) return { __index = function(t,i) return cfg.id_handlers[k][i] end } end;
for k, v in pairs( id_list ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
-- fallback to read-only cfg
handler = setmetatable( { ['id'] = v }, fallback(k) );
if handler.mode == 'external' then
table.insert( new_list, {handler.label, external_link_id( handler ) } );
elseif handler.mode == 'internal' then
table.insert( new_list, {handler.label, internal_link_id( handler ) } );
elseif handler.mode ~= 'manual' then
error( cfg.messages['unknown_ID_mode'] );
elseif k == 'DOI' then
table.insert( new_list, {handler.label, doi( v, options.DoiBroken ) } );
elseif k == 'ARXIV' then
table.insert( new_list, {handler.label, arxiv( v, options.Class ) } );
elseif k == 'ASIN' then
table.insert( new_list, {handler.label, amazon( v, options.ASINTLD ) } );
elseif k == 'LCCN' then
table.insert( new_list, {handler.label, lccn( v ) } );
elseif k == 'OL' or k == 'OLA' then
table.insert( new_list, {handler.label, openlibrary( v ) } );
elseif k == 'PMC' then
table.insert( new_list, {handler.label, pmc( v, options.Embargo ) } );
elseif k == 'PMID' then
table.insert( new_list, {handler.label, pmid( v ) } );
elseif k == 'ISMN' then
table.insert( new_list, {handler.label, ismn( v ) } );
elseif k == 'ISSN' then
table.insert( new_list, {handler.label, issn( v ) } );
elseif k == 'EISSN' then
table.insert( new_list, {handler.label, issn( v, true ) } ); -- true distinguishes eissn from issn
elseif k == 'ISBN' then
local ISBN = internal_link_id( handler );
if not check_isbn( v ) and not is_set(options.IgnoreISBN) then
ISBN = ISBN .. set_error( 'bad_isbn', {}, false, " ", "" );
end
table.insert( new_list, {handler.label, ISBN } );
elseif k == 'USENETID' then
table.insert( new_list, {handler.label, message_id( v ) } );
else
error( cfg.messages['unknown_manual_ID'] );
end
end
local function comp( a, b ) -- used in following table.sort()
return a[1] < b[1];
end
table.sort( new_list, comp );
for k, v in ipairs( new_list ) do
new_list[k] = v[2];
end
return new_list;
end
 
 
--[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------
 
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for
any of the parameters listed in each cfg.id_handlers['...'].parameters.  If found, adds the parameter and value to
the identifier list.  Emits redundant error message is more than one alias exists in args
 
]]
 
local function extract_ids( args )
local id_list = {}; -- list of identifiers found in args
for k, v in pairs( cfg.id_handlers ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
v = select_one( args, v.parameters, 'redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present
if is_set(v) then id_list[k] = v; end -- if found in args, add identifier to our list
end
return id_list;
end
 
 
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
 
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
 
]]
 
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
cfg = cfg_table_ptr;
 
is_set = utilities_page_ptr.is_set; -- import functions from select Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array;
set_error = utilities_page_ptr.set_error;
select_one = utilities_page_ptr.select_one;
add_maint_cat = utilities_page_ptr.add_maint_cat;
 
z = utilities_page_ptr.z; -- table of tables in Module:Citation/CS1/Utilities
end
 
 
 
return {
build_id_list = build_id_list,
extract_ids = extract_ids,
is_embargoed = is_embargoed;
set_selected_modules = set_selected_modules;
}
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.