|
|
第1行: |
第1行: |
| --[[--------------------------< I M P O R T E D _ F U N C T I O N S _ A N D _ V A R I B L E S >----------------- | | -- [[ |
| ]]
| | --本页面被CleanNote清除。 |
|
| |
|
| local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
| | --此内容违反Note.ms的整洁。 |
| local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
| |
|
| |
|
| local dates, year_date_check; -- functions in Module:Citation/CS1/Date_validation
| | --如果这个信息令你反感,你可以清除。 |
| local add_maint_cat, append_error, make_error_tail, reset_error, set_error, select_one, throw_error;
| |
| -- error-related functions in Module:Citation/CS1/Error
| |
| local first_set, hyphen_to_dash, is_set, in_array, substitute; -- simple functions in Module:Citation/CS1/Utilities
| |
| local has_invisible_chars, kern_quotes, pend_separator, safe_join, wrap_style, wrap_msg;
| |
| -- style-related functions in Module:Citation/CS1/Utilities
| |
| local check_for_external_link, make_external_link, make_internal_link; -- link-related functions in Module:Citation/CS1/Links
| |
| local extract_ids, build_id_list, is_embargoed, extract_id_access_levels; -- functions in Module:Citation/CS1/Identifiers
| |
| local get_people, format_people; -- functions in Module:Citation/CS1/People
| |
| local COinS; -- functions in Module:Citation/CS1/COinS
| |
| local script_concatenate, language_parameter; -- functions in Module:Citation/CS1/Language
| |
|
| |
|
| local function load_modules (module_path, module_suffix)
| | --如果你想加入我们,请访问notewiki.github.io#CleanNote。 |
| cfg = mw.loadData (module_path .. 'Configuration' .. module_suffix);
| | -- ]] |
| whitelist = mw.loadData (module_path .. 'Whitelist' .. module_suffix);
| |
| local validation = require (module_path .. 'Date_validation' .. module_suffix);
| |
| local identifiers = require (module_path .. 'Identifiers' .. module_suffix);
| |
| local utilities = require (module_path .. 'Utilities' .. module_suffix);
| |
| local people = require (module_path .. 'People' .. module_suffix);
| |
| local links = require (module_path .. 'Links' .. module_suffix);
| |
| local errors = require (module_path .. 'Error' .. module_suffix);
| |
| local coins = require (module_path .. 'COinS' .. module_suffix);
| |
| local languages = require (module_path .. 'Language' .. module_suffix);
| |
| | |
| utilities.set_selected_modules (cfg);
| |
| links.set_selected_modules (utilities, errors);
| |
| errors.set_selected_modules (cfg, utilities, links);
| |
| identifiers.set_selected_modules (cfg, utilities, errors, links, validation);
| |
| people.set_selected_modules (cfg, utilities, errors, links);
| |
| coins.set_selected_modules (cfg, utilities, links);
| |
| languages.set_selected_modules (utilities, errors);
| |
| | |
| dates = validation.dates; -- imported functions
| |
| year_date_check = validation.year_date_check;
| |
|
| |
| first_set = utilities.first_set;
| |
| hyphen_to_dash = utilities.hyphen_to_dash;
| |
| is_set = utilities.is_set;
| |
| in_array = utilities.in_array;
| |
| substitute = utilities.substitute;
| |
|
| |
| has_invisible_chars = utilities.has_invisible_chars;
| |
| kern_quotes = utilities.kern_quotes;
| |
| pend_separator = utilities.pend_separator;
| |
| safe_join = utilities.safe_join;
| |
| wrap_style = utilities.wrap_style;
| |
| wrap_msg = utilities.wrap_msg;
| |
|
| |
| make_external_link = links.make_external_link;
| |
| make_internal_link = links.make_internal_link;
| |
| check_for_external_link = links.check_for_external_link;
| |
|
| |
| add_maint_cat = errors.add_maint_cat;
| |
| append_error = errors.append_error;
| |
| make_error_tail = errors.make_error_tail;
| |
| reset_error = errors.reset_error;
| |
| set_error = errors.set_error;
| |
| select_one = errors.select_one;
| |
| throw_error = errors.throw_error;
| |
|
| |
| extract_ids = identifiers.extract_ids;
| |
| build_id_list = identifiers.build_id_list;
| |
| is_embargoed = identifiers.is_embargoed;
| |
| extract_id_access_levels = identifiers.extract_id_access_levels;
| |
|
| |
| get_people = people.get_people;
| |
| format_people = people.format_people;
| |
|
| |
| COinS = coins.COinS;
| |
|
| |
| script_concatenate = languages.script_concatenate;
| |
| language_parameter = languages.language_parameter;
| |
| | |
| end
| |
| | |
| --[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
| |
| | |
| Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the
| |
| offending parameter name to the error message.
| |
| | |
| ]]
| |
| | |
| local function deprecated_parameter (name)
| |
| append_error ('deprecated_params', {name});
| |
| end
| |
| | |
| --[[--------------------------< D I S C A R D _ P A R A M E T E R >--------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function discard_parameter (name, label, new_value)
| |
| if is_set (name) then
| |
| append_error ('parameter_discarded', label);
| |
| end
| |
| return new_value;
| |
| end
| |
| | |
| --[[--------------------------< S A N I T I Z E D _ P A R A M E T E R _ V A L U E >------------------------
| |
| | |
| This function is used to validate a parameter's assigned value for those parameters that have only a limited number
| |
| of allowable values (e.g. yes, y, true, no, etc). If the parameter value is empty or is in the list of allowed values,
| |
| the function returns the value; else, it emits an error message and returns the default value.
| |
| | |
| ]]
| |
| | |
| local function sanitized_parameter_value (value, name, key, default)
| |
| if not is_set (value) then
| |
| return value; -- an empty parameter is ok
| |
| elseif in_array (value:lower(), cfg.keywords[key]) then
| |
| return value;
| |
| else
| |
| append_error ('invalid_param_val', {name, value}); -- not an allowed value so add error message
| |
| return default;
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< E X T R A _ T E X T _ I N _ P A R A M E T E R _ C H E C K >------------------------------
| |
| | |
| ]]
| |
| | |
| local function extra_text_in_parameter_check (value, type)
| |
|
| |
| local good_patterns = cfg.extra_text_pattern[type]['good'];
| |
| local bad_patterns = cfg.extra_text_pattern[type]['bad'];
| |
|
| |
| for _, pattern in pairs (good_patterns) do
| |
| if value:match (pattern) then
| |
| return;
| |
| end
| |
| end
| |
|
| |
| for _, pattern in pairs (bad_patterns) do
| |
| if value:match (pattern) then
| |
| add_maint_cat ('extra_text', type);
| |
| return;
| |
| end
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< V A L I D A T E _ D A T E >-------------------------------------------------------
| |
| | |
| Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where
| |
| we get the date used in the metadata.
| |
| | |
| Date validation supporting code is in Module:Citation/CS1/Date_validation
| |
| ]]
| |
| | |
| local function validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, origin)
| |
| local error_message = '';
| |
| -- AirDate has been promoted to Date so not necessary to check it
| |
| anchor_year, error_message = dates ({['access-date']=AccessDate, ['archive-date']=ArchiveDate, ['date']=Date, ['doi-broken-date']=DoiBroken,
| |
| ['embargo']=Embargo, ['lay-date']=LayDate, ['publication-date']=PublicationDate, ['year']=Year}, COinS_date);
| |
| | |
| if is_set (Year) then
| |
| if is_set (Date) then -- both |date= and |year= not normally needed;
| |
| local mismatch = year_date_check (Year, Date)
| |
| if 0 == mismatch then -- |year= does not match a year-value in |date=
| |
| append_error ('date_year_mismatch', {origin});
| |
| elseif 1 == mismatch then -- |year= matches year-value in |date=
| |
| add_maint_cat ('date_year');
| |
| end
| |
| end
| |
| anchor_year = Year; -- Year first for legacy citations and for YMD dates that require disambiguation
| |
| end
| |
| | |
| if is_set (error_message) then
| |
| append_error ('bad_date', {error_message}); -- add this error message
| |
| end
| |
| return anchor_year;
| |
| end
| |
| | |
| --[[--------------------------< D I S C A R D _ C H A P T E R >-------------------------------------------------------
| |
| 仅为保持兼容性而设置。理论上可以直接调用discard_parameter()丢弃相关参数。
| |
| ]]
| |
|
| |
| local function discard_chapter (args)
| |
| local chap_param;
| |
| if is_set (args['Chapter']) then -- get a parameter name from one of these chapter related meta-parameters
| |
| chap_param = args:ORIGIN ('Chapter');
| |
| elseif is_set (args['TransChapter']) then
| |
| chap_param = args:ORIGIN ('TransChapter');
| |
| elseif is_set (args['ChapterURL']) then
| |
| chap_param = args:ORIGIN ('ChapterURL');
| |
| elseif is_set (args['ScriptChapter']) then
| |
| chap_param = args:ORIGIN ('ScriptChapter')
| |
| elseif is_set (args['ChapterFormat']) then
| |
| chap_param = args:ORIGIN ('ChapterFormat')
| |
| elseif is_set (args['ChapterUrlAccess']) then
| |
| chap_param = args:ORIGIN ('ChapterUrlAccess')
| |
| end
| |
| if is_set (chap_param) then -- if we found one
| |
| append_error ('chapter_ignored', {chap_param}); -- add error message
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< C R E A T E _ U R L _ O B J E C T >------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function create_url_object (url, source, fmt, fmt_source, access, access_source)
| |
| return {
| |
| ['url'] = is_set (url) and url or '',
| |
| ['origin'] = is_set (source) and source or '',
| |
| ['access'] = is_set (access) and sanitized_parameter_value (access, access_source, 'url-access', '') or '',
| |
| ['access-origin'] = is_set (access_source) and access_source or '',
| |
| ['format'] = is_set (fmt) and fmt or '',
| |
| ['format-origin'] = is_set (fmt_source) and fmt_source or '',
| |
| ['access-text'] = ''
| |
| }
| |
| end
| |
| | |
| --[[--------------------------< S E T _ T I T L E T Y P E >----------------------------------------------------
| |
| | |
| This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults.
| |
| Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none).
| |
| | |
| ]]
| |
| | |
| local function set_titletype (cite_class, title_type)
| |
| if is_set (title_type) then
| |
| if 'none' == title_type then
| |
| title_type = ''; -- if |type=none then type parameter not displayed
| |
| end
| |
| return title_type; -- if |type= has been set to any other value use that value
| |
| end
| |
| | |
| return cfg.title_types[cite_class] or ''; -- set template's default title type; else empty string for concatenation
| |
| end
| |
| | |
| --[[--------------------------< S E T _ N O _ T R A C K I N G _ C A T S >-----------------------------------------
| |
| | |
| check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories
| |
| | |
| ]]
| |
| | |
| local function set_no_tracking_cats (no_tracking, no_tracking_source, this_page)
| |
| local no_tracking_cats = sanitized_parameter_value (no_tracking, no_tracking_source, 'yes_true_y', nil);
| |
| if not is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page
| |
| if in_array (this_page.nsText, cfg.uncategorized_namespaces) then
| |
| return true; -- set no_tracking_cats
| |
| end
| |
| for _,v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns
| |
| if this_page.text:match (v) then -- test page name against each pattern
| |
| return true; -- set no_tracking_cats; bail out if one is found
| |
| end
| |
| end
| |
| return false;
| |
| else
| |
| return true;
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< S E T _ C S 1 _ S T Y L E >----------------------------------------------------
| |
| | |
| Set style settings for CS1 citation templates. Returns separator and postscript settings
| |
| | |
| ]]
| |
| | |
| local function set_cs1_style (ps)
| |
| if not is_set (ps) then -- unless explicitely set to something
| |
| ps = '.'; -- terminate the rendered citation with a period
| |
| end
| |
| return '.', ps; -- separator is a full stop
| |
| end
| |
| | |
| --[[--------------------------< S E T _ C S 2 _ S T Y L E >----------------------------------------------------
| |
| | |
| Set style settings for CS2 citation templates. Returns separator, postscript, ref settings
| |
| | |
| ]]
| |
| | |
| local function set_cs2_style (ps, ref)
| |
| if not is_set (ps) then -- if |postscript= has not been set, set cs2 default
| |
| ps = ''; -- make sure it isn't nil
| |
| end
| |
| if not is_set (ref) then -- if |ref= is not set
| |
| ref = 'harv'; -- set default |ref=harv
| |
| end
| |
| return ',', ps, ref; -- separator is a comma
| |
| end
| |
| | |
| --[[--------------------------< G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S >----------------------
| |
| | |
| When |mode= is not set or when its value is invalid, use config.CitationClass and parameter values to establish
| |
| rendered style.
| |
| | |
| ]]
| |
| | |
| local function get_settings_from_cite_class (ps, ref, cite_class)
| |
| local sep;
| |
| if (cite_class == 'citation') then -- for citation templates (CS2)
| |
| sep, ps, ref = set_cs2_style (ps, ref);
| |
| else -- not a citation template so CS1
| |
| sep, ps = set_cs1_style (ps);
| |
| end
| |
| | |
| return sep, ps, ref -- return them all
| |
| end
| |
| | |
| --[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------
| |
| | |
| Establish basic style settings to be used when rendering the citation. Uses |mode= if set and valid or uses
| |
| config.CitationClass from the template's #invoke: to establish style.
| |
| | |
| ]]
| |
| | |
| local function set_style (mode, mode_source, ps, ref, quote, cite_class)
| |
| local sep;
| |
| mode = sanitized_parameter_value (mode, mode_source, 'mode', ''):lower();
| |
| if 'cs2' == mode then -- if this template is to be rendered in CS2 (citation) style
| |
| sep, ps, ref = set_cs2_style (ps, ref);
| |
| elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style
| |
| sep, ps = set_cs1_style (ps);
| |
| else -- anything but cs1 or cs2
| |
| sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass
| |
| end
| |
| if 'none' == ps:lower() or is_set (quote) then -- if assigned value is 'none' then set it to empty string
| |
| ps = ''; -- also cs1|2 does not supply terminal punctuation when |quote= is set
| |
| end
| |
|
| |
| return sep, ps, ref
| |
| end
| |
| | |
| --[[--------------------------< S W A P _ U R L S >--------------------------------------------------------------
| |
| | |
| ]] | |
| | |
| local function swap_urls (url_object, chapter_url_object, archive_url_object, dead_url)
| |
| local original_url_object = create_url_object ();
| |
| local is_dead = in_array (dead_url, cfg.keywords['deadurl-live']); -- used later when assembling archived text
| |
|
| |
| if is_set (archive_url_object['url']) then
| |
| if is_set (url_object['url']) then
| |
| original_url_object = url_object;
| |
| if not is_dead then
| |
| url_object = archive_url_object;
| |
| end
| |
| elseif is_set (chapter_url_object['url']) then -- URL not set so if chapter-url is set apply archive url to it
| |
| original_url_object = chapter_url_object;
| |
| if not is_dead then
| |
| chapter_url_object = archive_url_object;
| |
| end
| |
| end
| |
| end
| |
| return original_url_object, url_object, chapter_url_object;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ U R L _ A C C E S S _ T E X T >---------------------------------------
| |
| | |
| 从x-url-access系列参数生成相应的图标;兼容既有registration, subscription参数,优先级x-url-access > subscription > registration。
| |
| | |
| ]]
| |
| | |
| local function format_url_access_text (url_object, subscription_required, registration_required)
| |
| local access_text = '';
| |
| local redundant = false;
| |
| local access = url_object['access'];
| |
| local reg = false;
| |
| local sub = false;
| |
| if is_set (access) then
| |
| if (access == 'limited') then
| |
| access_text = cfg.presentation['limited']; -- 有限度免费访问
| |
| elseif (access == 'registration') then
| |
| access_text = cfg.presentation['registration']; -- 需要免费注册
| |
| reg = true;
| |
| elseif (access == 'subscription') then
| |
| access_text = cfg.presentation['subscription']; -- 需要付费订阅
| |
| sub = true;
| |
| else
| |
| access_text = '';
| |
| end
| |
| if is_set (subscription_required) or is_set (registration_required) then
| |
| redundant = true;
| |
| end
| |
| else
| |
| if is_set (subscription_required) then
| |
| access_text = cfg.presentation['subscription']; -- 需要免费注册
| |
| sub = true;
| |
| if is_set (registration_required) then
| |
| redundant = true;
| |
| end
| |
| elseif is_set (registration_required) then
| |
| access_text = cfg.presentation['registration']; -- 需要付费订阅
| |
| reg = true
| |
| else
| |
| access_text = '';
| |
| end
| |
| end
| |
| if is_set (url_object ['url']) then
| |
| url_object['access-text'] = access_text;
| |
| if sub then
| |
| add_maint_cat ('subscription');
| |
| elseif reg then
| |
| add_maint_cat ('registration');
| |
| end
| |
| else
| |
| -- 预留报错
| |
| end
| |
| return redundant;
| |
| end
| |
| | |
| --[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >----------------------------------------
| |
| | |
| returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume
| |
| or formatted issue, or an empty string if neither are set.
| |
| | |
| ]]
| |
|
| |
| local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower)
| |
| if not is_set (volume) and not is_set (issue) then
| |
| return '';
| |
| end
| |
|
| |
| if 'magazine' == cite_class or (cite_class =='map' and 'magazine' == origin) then
| |
| if is_set (volume) and is_set (issue) then
| |
| return wrap_msg ('vol-no', {sepc, volume, issue}, lower);
| |
| elseif is_set (volume) then
| |
| return wrap_msg ('vol', {sepc, volume}, lower);
| |
| else
| |
| return wrap_msg ('issue', {sepc, issue}, lower);
| |
| end
| |
| end
| |
|
| |
| local vol = '';
| |
|
| |
| if is_set (volume) then
| |
| if (6 < mw.ustring.len (volume)) then
| |
| vol = wrap_msg ('j-vol', {sepc, volume}, lower);
| |
| else
| |
| vol = wrap_style ('vol-bold', hyphen_to_dash (volume));
| |
| end
| |
| end
| |
| if is_set (issue) then
| |
| return vol .. wrap_msg ('j-issue', issue, lower);
| |
| end
| |
| return vol;
| |
| end
| |
| | |
| --[[-------------------------< F O R M A T _ I N S O U R C E _ L O C A T I O N >----------------------------------
| |
| | |
| Build insource_location meta-parameter from |page(s)= , |sheet(s)= , |at= and other relevant parameters.
| |
| | |
| ]]
| |
| | |
| local function format_insource_location (page, pages, sheet, sheets, at, minutes, time, time_caption, section, sections, inset, cite_class, origin, sepc, nopp, lower)
| |
| local text = '';
| |
|
| |
| if is_set (sheet) then
| |
| if 'journal' == origin then
| |
| text = wrap_msg ('j-sheet', sheet, lower);
| |
| else
| |
| text = wrap_msg ('sheet', {sepc, sheet}, lower);
| |
| end
| |
| elseif is_set (sheets) then
| |
| if 'journal' == origin then
| |
| text = wrap_msg ('j-sheets', sheets, lower);
| |
| else
| |
| text = wrap_msg ('sheets', {sepc, sheets}, lower);
| |
| end
| |
| end
| |
| | |
| local is_journal = 'journal' == cite_class or (cite_class == 'map' and 'journal' == origin);
| |
| if is_set (page) then
| |
| if is_journal then
| |
| text = wrap_msg ('j-page(s)', page, lower);
| |
| elseif not is_set (nopp) then
| |
| text = wrap_msg ('p-prefix', {sepc, page}, lower);
| |
| else
| |
| text = wrap_msg ('nopp', {sepc, page}, lower);
| |
| end
| |
| elseif is_set (pages) then
| |
| if is_journal then
| |
| text = wrap_msg ('j-page(s)', pages, lower);
| |
| elseif tonumber (pages) ~= nil and not is_set (nopp) then -- if pages is only digits, assume a single page number
| |
| text = wrap_msg ('p-prefix', {sepc, pages}, lower);
| |
| elseif not is_set (nopp) then
| |
| text = wrap_msg ('pp-prefix', {sepc, pages}, lower);
| |
| else
| |
| text = wrap_msg ('nopp', {sepc, pages}, lower);
| |
| end
| |
| end
| |
|
| |
| if is_set (minutes) then
| |
| text = pend_separator (wrap_msg ('minutes', minutes, lower), sepc, true) .. text;
| |
| else
| |
| if is_set (time) then
| |
| if not is_set (time_caption) then
| |
| text = pend_separator (wrap_msg ('event', time, lower), sepc, true) .. text;
| |
| else
| |
| text = pend_separator (time_caption .. ' ' .. time .. text, sepc, true);
| |
| end
| |
| end
| |
| end
| |
|
| |
| text = text .. pend_separator (at, sepc, true);
| |
| text = text .. pend_separator (wrap_msg ('inset', inset, lower), sepc, true);
| |
|
| |
| if is_set (sections) then
| |
| text = text .. pend_separator (wrap_msg ('sections', sections, lower), sepc, true);
| |
| elseif is_set (section) then
| |
| text = text .. pend_separator (wrap_msg ('section', section, lower), sepc, true);
| |
| end
| |
|
| |
| return text;
| |
| end
| |
| | |
| --[[-------------------------< F O R M A T _ P U B L I S H E R >------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_publisher (publisher_name, publication_place, periodical, cite_class, sepc)
| |
| local publisher = '';
| |
|
| |
| if is_set (publisher_name) then
| |
| if is_set (publication_place) then
| |
| publisher = publication_place .. ': ' .. publisher_name;
| |
| else
| |
| publisher = publisher_name;
| |
| end
| |
| elseif is_set (publication_place) then
| |
| publisher = publication_place;
| |
| end
| |
|
| |
| if is_set (publisher) then
| |
| if is_set (periodical) and
| |
| not in_array (cite_class, {'encyclopaedia', 'web', 'pressrelease', 'podcast'}) then
| |
| publisher = ' (' .. publisher .. ')';
| |
| else
| |
| publisher = pend_separator (publisher, sepc, true);
| |
| end
| |
| end
| |
| return publisher;
| |
| end
| |
| | |
| --[[-------------------------< F O R M A T _ L I N K >-------------------------------------------------
| |
| | |
| Format an external link that may or may not be raw.
| |
| | |
| ]]
| |
| | |
| local function format_external_link (text, url_object, sepc)
| |
| if is_set (text) then
| |
| if is_set (url_object['url']) then
| |
| text = make_external_link (url_object['url'], text, url_object['origin']);
| |
| end
| |
| text = pend_separator (text .. url_object['format'], sepc, true);
| |
| elseif is_set (url_object['url']) then
| |
| text = make_external_link (url_object['url'], nil, url_object['origin']);
| |
| end
| |
| return text;
| |
| end
| |
| | |
| --[[-------------------------< F O R M A T _ C O N F E R E N C E >----------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_conference (conference, conference_url_object, periodical, cite_class, sepc)
| |
| local conf_text = format_external_link (conference, conference_url_object, sepc);
| |
| if 'speech' == cite_class and is_set (periodical) then
| |
| -- if cite speech, periodical (perhaps because of an included |website= or |journal= parameter) is set;
| |
| conf_text = pend_separator (conf_text, sepc, false); -- then add appropriate punctuation to the end of the conference variable if set.
| |
| end
| |
| return conf_text;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------------------------------
| |
| | |
| Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single Chapter meta-
| |
| parameter (chapter_url_source used for error messages).
| |
| | |
| ]]
| |
| | |
| local function format_chapter_title (scriptchapter, chapter, transchapter, chapter_url_object, no_quotes, cite_class, title_type, sepc)
| |
| local chapter_error = '';
| |
|
| |
| if not is_set (chapter) then
| |
| chapter = ''; -- to be safe for concatenation
| |
| else
| |
| if false == no_quotes then
| |
| chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks
| |
| chapter = wrap_style ('quoted-title', chapter);
| |
| end
| |
| end
| |
| | |
| chapter = script_concatenate (chapter, scriptchapter) -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
| |
| | |
| if is_set (transchapter) then
| |
| transchapter = wrap_style ('trans-quoted-title', transchapter);
| |
| if is_set (chapter) then
| |
| chapter = chapter .. ' ' .. transchapter;
| |
| else -- here when transchapter without chapter or script-chapter
| |
| chapter = transchapter;
| |
| chapter_error = ' ' .. set_error ('trans_missing_title', {'chapter'});
| |
| end
| |
| end
| |
| if is_set (chapter_url_object['url']) then
| |
| chapter = make_external_link (chapter_url_object['url'], chapter, chapter_url_object['origin']) .. chapter_url_object['access-text'];
| |
| -- adds bare_url_missing_title error if appropriate
| |
| end
| |
| chapter = chapter .. chapter_error;
| |
|
| |
| if is_set (chapter) then
| |
| if 'map' == cite_class and is_set (title_type) then
| |
| chapter = chapter .. ' ' .. title_type;
| |
| end
| |
| chapter = pend_separator (chapter .. chapter_url_object['format'], sepc, false);
| |
| else -- |chapter= not set but |chapter-format= is so ...
| |
| chapter = pend_separator (chapter_url_object['format'], sepc, false); -- ... ChapterFormat has error message, we want to see it
| |
| end
| |
|
| |
| return chapter;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ M A I N _ T I T L E >------------------------------------------
| |
| | |
| Format the five title parameters: |script-title=, |title=, |trans-title=, |title-link=, and |url= into a single Title meta-
| |
| parameter (url_origin and title_link_origin used for error messages).
| |
| | |
| ]]
| |
| | |
| local function format_main_title (title, title_link, title_link_origin, script_title, trans_title, url_object, no_chapter_format, cite_class, periodical)
| |
| if is_set (title_link) and is_set (title) then
| |
| title = make_internal_link (title_link, title, title_link_origin);
| |
| end
| |
| if no_chapter_format or
| |
| ('map' == cite_class and is_set (periodical)) then -- special case for cite map when the map is in a periodical treat as an article
| |
| title = kern_quotes (title); -- if necessary, separate title's leading and trailing quote marks from Module provided quote marks
| |
| title = wrap_style ('quoted-title', title);
| |
|
| |
| title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
| |
| trans_title= wrap_style ('trans-quoted-title', trans_title );
| |
| elseif 'report' == cite_class then -- no styling for cite report
| |
| title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
| |
| trans_title= wrap_style ('trans-quoted-title', trans_title ); -- for cite report, use this form for trans-title
| |
| else
| |
| title = wrap_style ('italic-title', title);
| |
| title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
| |
| trans_title = wrap_style ('trans-italic-title', trans_title);
| |
| end
| |
| | |
| local trans_error = '';
| |
| if is_set (trans_title) then
| |
| if is_set (title) then
| |
| trans_title = ' ' .. trans_title;
| |
| else
| |
| trans_error = ' ' .. set_error ('trans_missing_title', {'title'});
| |
| end
| |
| end
| |
|
| |
| title = title .. trans_title;
| |
|
| |
| if is_set (title) then
| |
| if not is_set (title_link) and is_set (url_object['url']) then
| |
| title = make_external_link (url_object['url'], title, url_object['origin']) .. url_object['access-text'] .. trans_error .. url_object['format'];
| |
| url_object = create_url_object ();
| |
| else
| |
| title = title .. trans_error;
| |
| end
| |
| end
| |
| return title, url_object;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ F O R M A T >--------------------------------------------------------
| |
| | |
| Applies css style to |format=, |chapter-format=, etc. Also emits an error message if the format parameter does
| |
| not have a matching url parameter. If the format parameter is not set and the url contains a file extension that
| |
| is recognized as a pdf document by MediaWiki's commons.css, this code will set the format parameter to (PDF) with
| |
| the appropriate styling.
| |
| | |
| ]]
| |
| | |
| local function format_format (args)
| |
| for _, url_object in pairs (args) do
| |
| if is_set (url_object['format']) then
| |
| url_object['format'] = wrap_style ('format', url_object['format']); -- add leading space, parenthases, resize
| |
| if not is_set (url_object['url']) then
| |
| url_object['format'] = url_object['format'] .. set_error ('format_missing_url', {url_object['format-origin'], url_object['origin']});
| |
| -- add an error message
| |
| end
| |
| elseif is_set (url_object['url']) then
| |
| if url_object['url']:match ('%.pdf[%?#]?') or url_object['url']:match ('%.PDF[%?#]?') then
| |
| -- format is not set so if url is a pdf file then
| |
| url_object['format'] = wrap_style ('format', 'PDF'); -- set format to pdf
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ A C C E S S D A T E >----------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_accessdate (accessdate, sepc, lower)
| |
| if is_set (accessdate) then -- first, wrap in nowrap span if date in appropriate format
| |
| if accessdate:match ('^%d%d%d%d%-%d%d%-%d%d$') then
| |
| accessdate = wrap_style ('nowrap1', accessdate); -- when accessdate is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.
| |
| elseif accessdate:match('^%a+%s*%d%d?,%s+%d%d%d%d$') or accessdate:match ('^%d%d?%s*%a+%s+%d%d%d%d$') then
| |
| local cap, cap2 = string.match (accessdate, '^(.*)%s+(%d%d%d%d)$');
| |
| accessdate = wrap_style ('nowrap2', {cap, cap2}); -- when accessdate is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY
| |
| end
| |
| accessdate = ' ' .. wrap_msg ('retrieved', accessdate, lower); -- add retrieved text
| |
| accessdate = wrap_style ('accessdate', {sepc, accessdate}); -- allow editors to hide accessdates
| |
| end
| |
| return accessdate;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ I D >----------------------------------------------------
| |
| ]]
| |
| | |
| local function format_id (id, docket, sepc, lower)
| |
| id = pend_separator (id, sepc, true);
| |
| return pend_separator (wrap_msg ('docket', docket, lower), sepc, true) .. id;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ Q U O T E >----------------------------------------------
| |
| ]]
| |
| | |
| local function format_quote (quote, sepc)
| |
| if is_set (quote) then
| |
| if quote:sub (1, 1) == '"' and quote:sub (-1, -1) == '"' then -- if first and last characters of quote are quote marks
| |
| quote = quote:sub (2, -2); -- strip them off
| |
| end
| |
| return pend_separator (wrap_style ('quoted-text', quote), sepc, true); -- wrap in <q>...</q> tags
| |
| end
| |
| return '';
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ A R C H I V E >------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_archive (archive_url_object, original_url_object, archive_date, dead_url, sepc, lower)
| |
| local archived = '';
| |
| if is_set (archive_url_object['url']) then
| |
| if not is_set (archive_date) then
| |
| archive_date = set_error ('archive_missing_date');
| |
| end
| |
| if in_array (dead_url, cfg.keywords['deadurl-live']) then
| |
| local arch_text = cfg.messages['archived'];
| |
| if (lower) then arch_text = arch_text:lower(); end;
| |
| archived = pend_separator (wrap_msg ('archived-not-dead', {make_external_link (archive_url_object['url'], arch_text, archive_url_object['origin']) .. archive_url_object['format'], archive_date }, lower), sepc, true);
| |
| if not is_set (original_url_object['url']) then
| |
| archived = archived .. ' ' .. set_error ('archive_missing_url');
| |
| end
| |
| elseif is_set (original_url_object['url']) then -- dead_url is not live, so it should be empty, dead or unfit
| |
| if in_array (dead_url, cfg.keywords['deadurl-unfit']) then
| |
| archived = pend_separator (wrap_msg('archived-unfit', archive_date, lower), sepc, true);
| |
| -- format already styled
| |
| else -- dead_url is empty or dead
| |
| archived = pend_separator (wrap_msg ('archived-dead',
| |
| {make_external_link (original_url_object['url'], cfg.messages['original'], original_url_object['origin']) .. original_url_object['access-text'] .. original_url_object['format'], archive_date }, lower), sepc, true);
| |
| -- format already styled
| |
| end
| |
| else
| |
| archived = pend_separator (wrap_msg ('archived-missing',
| |
| {set_error ('archive_missing_url'), archive_date }, lower), sepc, true);
| |
| end
| |
| elseif is_set (original_url_object['format']) then
| |
| archived = original_url_object['format']; -- if set and archive_url not set archive_format has error message
| |
| end
| |
| return archived;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ L A Y >---------------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_lay (lay_url_object, lay_date, lay_source, sepc, lower)
| |
| local lay = '';
| |
| if is_set (lay_url_object['url']) then
| |
| if is_set (lay_date) then lay_date = ' (' .. lay_date .. ')' end
| |
| if is_set (lay_source) then
| |
| lay_source = wrap_msg ('lay source', lay_source, lower);
| |
| else
| |
| lay_source = '';
| |
| end
| |
| local lay_sum = cfg.messages['lay summary'];
| |
| if lower then
| |
| lay_sum = lay_sum:lower();
| |
| end
| |
| lay = pend_separator (make_external_link (lay_url_object['url'], lay_sum, lay_url_object['origin']) .. lay_url_object['format'] .. lay_source .. lay_date, sepc, true);
| |
| else -- Test if |lay-format= is given without giving a |lay-url=
| |
| lay = pend_separator (lay_url_object['format'], sepc, true); -- if set and LayURL not set, then LayFormat has error message
| |
| end
| |
| return lay;
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ P E R I O D I C A L >------------------------------------
| |
| ]]
| |
| | |
| local function format_periodical (periodical, title, title_note, sepc)
| |
| if is_set (periodical) then
| |
| if is_set (title) or is_set (title_note) then
| |
| return pend_separator (wrap_style ('italic-title', periodical), sepc, true);
| |
| else
| |
| return wrap_style ('italic-title', periodical);
| |
| end
| |
| end
| |
| return '';
| |
| end
| |
| | |
| --[[--------------------------< A N C H O R _ I D >------------------------------------------------------------
| |
| | |
| Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise returns an empty string.
| |
| | |
| namelist is one of the contributor-, author-, or editor-name lists chosen in that order. year is Year or anchor_year.
| |
| | |
| ]]
| |
| | |
| local function anchor_id (namelist, year)
| |
| local names={}; -- a table for the one to four names and year
| |
| for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names
| |
| names[i] = v.last
| |
| if i == 4 then break end -- if four then done
| |
| end
| |
| table.insert (names, year); -- add the year at the end
| |
| local id = table.concat (names); -- concatenate names and year for CITEREF id
| |
| if is_set (id) then -- if concatenation is not an empty string
| |
| return 'CITEREF' .. id; -- add the CITEREF portion
| |
| else
| |
| return ''; -- return an empty string; no reason to include CITEREF id in this citation
| |
| end
| |
| end
| |
| | |
| --[[--------------------------< F O R M A T _ C I T A T I O N >--------------------------------------------
| |
| | |
| ]]
| |
| | |
| local function format_citation (body, cite_class, ref, namelist, year, ocins_output, no_tracking_cats)
| |
| local options = {};
| |
|
| |
| if is_set (cite_class) and cite_class ~= 'citation' then
| |
| options.class = 'citation ' .. cite_class; -- class=citation required for blue highlight when used with |ref=
| |
| else
| |
| options.class = 'citation';
| |
| end
| |
|
| |
| if is_set (ref) and ref:lower() ~= 'none' then -- set reference anchor if appropriate
| |
| local id = ref
| |
| if ('harv' == ref ) then
| |
| id = anchor_id (namelist, year); -- go make the CITEREF anchor
| |
| end
| |
| options.id = id;
| |
| end
| |
|
| |
| if string.len (body:gsub ('<span[^>/]*>.-</span>', ''):gsub ('%b<>','')) <= 2 then
| |
| reset_error ({'err_cats'});
| |
| body = set_error ('empty_citation');
| |
| reset_error ({'msg_tail'});
| |
| end
| |
|
| |
| local text;
| |
|
| |
| if is_set (options.id) then
| |
| text = wrap_style ('citation-with-id', {mw.uri.anchorEncode (options.id), mw.text.nowiki (options.class), body});
| |
| else
| |
| text = wrap_style ('citation-no-id', {mw.text.nowiki (options.class), body});
| |
| end
| |
|
| |
| text = text .. wrap_style ('OCinS', ocins_output);
| |
| text = text .. make_error_tail (no_tracking_cats); -- append error/maintenance messages/categories to the citation
| |
|
| |
| return text;
| |
| end
| |
| | |
| --[[--------------------------< D E D U C E _ C I T A T I O N _ C L A S S >--------------------------------------
| |
| | |
| 如果citation_class为citation({{citation}}),根据periodical系列参数的设置情况推断实际的引用类型。
| |
| | |
| ]]
| |
| | |
| local function deduce_citation_class (A, naive_class)
| |
| local deduced_class;
| |
| local periodical = A['Periodical'];
| |
| local origin = A:ORIGIN ('Periodical');
| |
|
| |
| for cite_class, aliases in pairs (cfg.periodical.parameters) do
| |
| if cite_class ~= '_general' then
| |
| for _, aliase in pairs (aliases) do
| |
| if origin == aliase then
| |
| deduced_class = cite_class;
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| if (naive_class == 'citation') then
| |
| if is_set (deduced_class) then
| |
| return deduced_class, true;
| |
| end
| |
| elseif (naive_class ~= deduced_class) then
| |
| local check_list = cfg.periodical.compatibility[naive_class];
| |
| if is_set (check_list) then
| |
| if is_set (check_list['drop']) and in_array (deduced_class, check_list['drop']) then
| |
| A['Periodical'] = discard_parameter (periodical, origin, nil);
| |
| elseif is_set (check_list['warn']) and in_array (deduced_class, check_list['warn']) then
| |
| append_error ('periodical', {origin, naive_class, deduced_class, check_list['suggest']});
| |
| end
| |
| end
| |
| end
| |
| return naive_class, false;
| |
| end
| |
| | |
| | |
| --[[--------------------------< A R G U M E N T _ W R A P P E R >----------------------------------------------
| |
| | |
| Argument wrapper. This function provides support for argument mapping defined in the configuration file so that
| |
| multiple names can be transparently aliased to single internal variable.
| |
| | |
| ]]
| |
| | |
| local function argument_wrapper (args)
| |
| local origin = {};
| |
|
| |
| return setmetatable ({
| |
| ORIGIN = function (self, k)
| |
| local dummy = self[k]; --force the variable to be loaded.
| |
| return origin[k];
| |
| end
| |
| },
| |
| {
| |
| __index = function (tbl, k)
| |
| if origin[k] ~= nil then
| |
| return nil;
| |
| end
| |
|
| |
| local args, list, v = args, cfg.aliases[k];
| |
|
| |
| if type (list) == 'table' then
| |
| v, origin[k] = select_one (args, list, 'redundant_parameters');
| |
| if origin[k] == nil then
| |
| origin[k] = ''; -- Empty string, not nil
| |
| end
| |
| elseif list ~= nil then
| |
| v, origin[k] = args[list], list;
| |
| else
| |
| -- maybe let through instead of raising an error?
| |
| -- v, origin[k] = args[k], k;
| |
| throw_error ('unknown_argument_map');
| |
| end
| |
|
| |
| -- Empty strings, not nil;
| |
| if v == nil then
| |
| v = cfg.defaults[k] or '';
| |
| origin[k] = '';
| |
| end
| |
|
| |
| tbl = rawset (tbl, k, v);
| |
| return v;
| |
| end,
| |
| });
| |
| end
| |
| | |
| --[[--------------------------< D O _ C I T A T I O N >---------------------------------------------------------
| |
| | |
| This is the main function doing the majority of the citation formatting.
| |
| | |
| ]]
| |
| | |
| local function do_citation (config, args)
| |
|
| |
| --local variables that are not cs1 parameters
| |
| local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language
| |
| | |
| --[[
| |
| Load Input Parameters
| |
| The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.
| |
| ]]
| |
| local A = argument_wrapper (args);
| |
| local citation_class, did_duduction = deduce_citation_class (A, config.CitationClass);
| |
| | |
| -- Pick out the relevant fields from the arguments. Different citation templates
| |
| -- define different field names for the same underlying things.
| |
| ------------------------------------------------- Get dates
| |
| local Year = A['Year'];
| |
| local PublicationDate = A['PublicationDate'];
| |
| local OrigYear = A['OrigYear'];
| |
| local Date = A['Date'];
| |
| local Dateorigin = A:ORIGIN ('Date');
| |
| local LayDate = A['LayDate'];
| |
| ------------------------------------------------- Get title data
| |
| local Title = A['Title'];
| |
| local ScriptTitle = A['ScriptTitle'];
| |
| local Conference = A['Conference'];
| |
| local TransTitle = A['TransTitle'];
| |
| local TitleNote = A['TitleNote'];
| |
| local TitleLink = A['TitleLink'];
| |
| local TitleLinkorigin = A:ORIGIN ('TitleLink');
| |
|
| |
| local Periodical = A['Periodical'];
| |
| local Periodical_origin = A:ORIGIN ('Periodical'); -- get the name of the periodical parameter
| |
| | |
| local Series = A['Series'];
| |
|
| |
| local ConferenceURLobject = create_url_object (A['ConferenceURL'], A:ORIGIN ('ConferenceURL'), A['ConferenceFormat'], A:ORIGIN ('ConferenceFormat'));
| |
| local ArchiveURLobject = create_url_object (A['ArchiveURL'], A:ORIGIN ('ArchiveURL'), A['ArchiveFormat'], A:ORIGIN ('ArchiveFormat'));
| |
| local URLobject = create_url_object (A['URL'], A:ORIGIN ('URL'), A['Format'], A:ORIGIN ('Format'),A['UrlAccess'], A:ORIGIN ('UrlAccess'));
| |
| local TranscriptURLobject = create_url_object (A['TranscriptURL'], A:ORIGIN ('TranscriptURL'), A['TranscriptFormat'], A:ORIGIN ('TranscriptFormat'));
| |
| local LayURLobject = create_url_object (A['LayURL'], A:ORIGIN ('LayURL'), A['LayFormat'], A:ORIGIN ('LayFormat'));
| |
|
| |
| local Volume = A['Volume'];
| |
| local Issue = A['Issue'];
| |
| local Page = A['Page'];
| |
| local Pages = hyphen_to_dash (A['Pages']);
| |
| local At = A['At'];
| |
| | |
| if not in_array (citation_class, cfg.args_support['templates_using_volume']) then
| |
| Volume = discard_parameter (Volume, A:ORIGIN ('Volume'), nil);
| |
| end
| |
| if not in_array (citation_class, cfg.args_support['templates_using_issue']) then
| |
| if (A:ORIGIN ('Issue') ~= 'number') then
| |
| Issue = discard_parameter (Issue, A:ORIGIN ('Issue'), nil);
| |
| else
| |
| Issue = nil;
| |
| end
| |
| end
| |
| if in_array (citation_class, cfg.args_support['templates_not_using_page']) then
| |
| Page = discard_parameter (Page, A:ORIGIN ('Page'), nil);
| |
| Pages = discard_parameter (Pages, A:ORIGIN ('Pages'), nil);
| |
| At = discard_parameter (At, A:ORIGIN ('At'), nil);
| |
| end
| |
|
| |
| local Minutes = A['Minutes'];
| |
| local Time = A['Time'];
| |
| local TimeCaption = A['TimeCaption'];
| |
|
| |
| if not in_array (citation_class, cfg.args_support['templates_involving_time']) then
| |
| Minutes = discard_parameter (Minutes, A:ORIGIN ('Minutes'), nil);
| |
| Time = discard_parameter (Time, A:ORIGIN ('Time'), nil);
| |
| TimeCaption = discard_parameter (TimeCaption, A:ORIGIN ('TimeCaption'), nil);
| |
| end
| |
|
| |
| local Sheet = A['Sheet'];
| |
| local Sheets = A['Sheets'];
| |
| local Section = A['Section'];
| |
| local Sections = A['Sections'];
| |
| local Inset = A['Inset'];
| |
|
| |
| if not ('map' == citation_class) then
| |
| Sheet = discard_parameter (Sheet, A:ORIGIN ('Sheet'), nil);
| |
| Sheets = discard_parameter (Sheets, A:ORIGIN ('Sheets'), nil);
| |
| Sections = discard_parameter (Sections, A:ORIGIN ('Sections'), nil);
| |
| Inset = discard_parameter (Inset, A:ORIGIN ('Inset'), nil);
| |
| end
| |
|
| |
| --[[
| |
| 不知道哪个“天才”想出来的点子,现行引用模板里,section一个参数多个涵义。
| |
| 在书籍类引用中,section是章节名称,在地图引用中,section是地图的区域编号。
| |
| 所以一旦知道citation_class不是地图,就可以丢弃上述几乎全部参数,
| |
| 唯独section参数需要留到检查章节相关参数时一并进行检查。
| |
| ]]
| |
| | |
| local Chapter = '';
| |
| local ScriptChapter = '';
| |
| local TransChapter = '';
| |
| local ChapterURLobject;
| |
| local no_chapter_format = in_array (citation_class, cfg.args_support['templates_not_using_chapter_format']);
| |
|
| |
| if in_array (citation_class, cfg.args_support['templates_not_using_chapter']) then
| |
| ChapterURLobject = create_url_object ();
| |
| discard_chapter (A);
| |
| if not ('map' == citation_class) then
| |
| Section = discard_parameter (Section, A:ORIGIN ('Section'), nil);
| |
| end
| |
| else
| |
| Chapter = A['Chapter'];
| |
| ScriptChapter = A['ScriptChapter'];
| |
| TransChapter = A['TransChapter'];
| |
| ChapterURLobject = create_url_object (A['ChapterURL'], A:ORIGIN ('ChapterURL'), A['ChapterFormat'], A:ORIGIN ('ChapterFormat'), A['ChapterUrlAccess'], A:ORIGIN ('ChapterUrlAccess'));
| |
| if is_set (Chapter) then
| |
| if is_set (Section) then
| |
| select_one (args, {'chapter', 'contribution', 'section'}, 'redundant_parameters');
| |
| end
| |
| else
| |
| Chapter = Section;
| |
| Section = nil;
| |
| end
| |
| end
| |
|
| |
| local Edition = A['Edition'];
| |
| local PublicationPlace = A['PublicationPlace']
| |
| local Place = A['Place'];
| |
|
| |
| local PublisherName = A['PublisherName'];
| |
| local RegistrationRequired = sanitized_parameter_value (A['RegistrationRequired'], A:ORIGIN ('RegistrationRequired'), 'yes_true_y', nil);
| |
| local SubscriptionRequired = sanitized_parameter_value (A['SubscriptionRequired'], A:ORIGIN ('SubscriptionRequired'), 'yes_true_y', nil);
| |
|
| |
| local Via = A['Via'];
| |
| local AccessDate = A['AccessDate'];
| |
| local ArchiveDate = A['ArchiveDate'];
| |
| local Agency = A['Agency'];
| |
| local DeadURL = sanitized_parameter_value (A['DeadURL'], A:ORIGIN ('DeadURL'), 'deadurl', '');
| |
| | |
| local Language = A['Language'];
| |
| local DoiBroken = A['DoiBroken'];
| |
| local ID = A['ID'];
| |
| local ASINTLD = A['ASINTLD'];
| |
| local IgnoreISBN = sanitized_parameter_value (A['IgnoreISBN'], A:ORIGIN ('IgnoreISBN'), 'yes_true_y', nil);
| |
|
| |
| local Embargo = A['Embargo'];
| |
| local Class = A['Class']; -- arxiv class identifier
| |
| | |
| local ID_list = extract_ids (args);
| |
| local ID_access_levels = extract_id_access_levels (args, ID_list);
| |
| | |
| local LaySource = A['LaySource'];
| |
| local Transcript = A['Transcript'];
| |
| | |
| local no_tracking_cats = set_no_tracking_cats (A['NoTracking'], A:ORIGIN ('NoTracking'), this_page);
| |
|
| |
| local Quote = A['Quote'];
| |
| local sepc, PostScript, Ref = set_style (A['Mode'], A:ORIGIN ('Mode'), A['PostScript'], A['Ref'], Quote, config.CitationClass);
| |
| if is_set (Quote) and is_set (A['PostScript']) then
| |
| select_one (args, {'postscript', 'quote', 'quotation'}, 'redundant_parameters');
| |
| end
| |
|
| |
| local use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text
| |
| | |
| -- check for insource-location-related parameters like |page=, |pages= or |at=. 请注意section参数有歧义,如果section跟书有关系,上面已经被清空了,这里不纳入检查。
| |
| select_one (args, {'at', 'time', 'minutes'}, 'redundant_parameters');
| |
| select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'time', 'minutes', 'sheet', 'sheets'}, 'redundant_parameters');
| |
| if is_set (Section) then
| |
| select_one (args, {'at', 'section', 'sections'}, 'redundant_parameters');
| |
| else
| |
| select_one (args, {'at', 'sections'}, 'redundant_parameters');
| |
| end
| |
| -- Dummy calls simply to get the error messages and categories
| |
| local NoPP = sanitized_parameter_value (A['NoPP'], A:ORIGIN ('NoPP'), 'yes_true_y', nil);
| |
| | |
| if is_set (Page) then
| |
| if is_set (Pages) or is_set (At) then
| |
| Pages = ''; -- unset the others
| |
| At = '';
| |
| end
| |
| extra_text_in_parameter_check (Page, 'page'); -- add this page to maint cat if |page= value begins with what looks like p. or pp.
| |
| elseif is_set (Pages) then
| |
| if is_set (At) then
| |
| At = ''; -- unset
| |
| end
| |
| extra_text_in_parameter_check (Pages, 'page'); -- add this page to maint cat if |pages= value begins with what looks like p. or pp.
| |
| end
| |
| | |
| -- both |publication-place= and |place= (|location=) allowed if different
| |
| if not is_set (PublicationPlace) and is_set (Place) then
| |
| PublicationPlace = Place; -- promote |place= (|location=) to |publication-place
| |
| end
| |
|
| |
| if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same
| |
|
| |
| if is_set (Edition) then
| |
| extra_text_in_parameter_check (Edition, 'edition');
| |
| end
| |
|
| |
| ------------------------------------------------- Get people
| |
| local NameListFormat = sanitized_parameter_value (A['NameListFormat'], A:ORIGIN ('NameListFormat'), 'name-list-format', '');
| |
| local LastAuthorAmp = sanitized_parameter_value (A['LastAuthorAmp'], A:ORIGIN ('LastAuthorAmp'), 'yes_true_y', nil);
| |
| local contributors_valid = in_array (citation_class, cfg.args_support['templates_using_contributor']);
| |
|
| |
| local Authors, Contributors, Editors, Translators, Contribution, NameList, multiple_editors, has_contributors =
| |
| get_people (
| |
| {
| |
| vauthors = A['Vauthors'], authors = A['Authors'], veditors = A['Veditors'], editors = A['Editors'], contribution = A['Contribution'], coauthors = A['Coauthors']
| |
| }, {
| |
| displayauthors = A['DisplayAuthors'], displayeditors = A['DisplayEditors'], contributorsvalid = contributors_valid, namelistformat = NameListFormat, lastauthoramp = LastAuthorAmp
| |
| }, args, this_page.name
| |
| ); -- (co-)authors, contributors, editors and translators
| |
|
| |
| local TitleType = set_titletype (citation_class, A['TitleType']); -- handle type parameter for those CS1 citations that have default values
| |
|
| |
| -- special case for cite thesis
| |
| local Degree = A['Degree'];
| |
| if 'thesis' == citation_class then
| |
| if (is_set (Degree)) then
| |
| TitleType = wrap_msg ('thesis with type', Degree, use_lowercase);
| |
| else
| |
| TitleType = wrap_msg ('thesis no type', 'placeholder', use_lowercase);
| |
| end
| |
| else
| |
| Degree = discard_parameter (Degree, A:ORIGIN ('Degree'), nil);
| |
| end
| |
|
| |
| local Others = A['Others'];
| |
|
| |
| --[[
| |
| Parameter remapping for cite encyclopedia:
| |
| When the citation has these parameters:
| |
| |encyclopedia and |title then map |title to |article and |encyclopedia to |title
| |
| |encyclopedia and |article then map |encyclopedia to |title
| |
| |encyclopedia then map |encyclopedia to |title
| |
| | |
| |trans_title maps to |trans_chapter when |title is re-mapped
| |
| |url maps to |chapterurl when |title is remapped
| |
| | |
| All other combinations of |encyclopedia, |title, and |article are not modified
| |
| | |
| ]]
| |
| | |
| local Encyclopedia;
| |
| local Entry = A['Entry'];
| |
| | |
| if (citation_class == 'encyclopaedia') then -- test code for citation
| |
| local entry_redundant = false
| |
| Encyclopedia = Periodical;
| |
| if is_set (Periodical) then
| |
| if is_set (Title) or is_set (ScriptTitle) then
| |
| Chapter = Title;
| |
| ScriptChapter = ScriptTitle;
| |
| ScriptTitle = '';
| |
| TransChapter = TransTitle;
| |
| TransTitle = '';
| |
| ChapterURLobject = URLobject;
| |
| URLobject = create_url_object ();
| |
| if not is_set (ChapterURLobject['url']) and is_set (TitleLink) then
| |
| Chapter = make_internal_link (TitleLink, Chapter, TitleLinkorigin);
| |
| end
| |
| TitleLink = '';
| |
| entry_redundant = is_set (Entry);
| |
| elseif is_set (Entry) then
| |
| Chapter = Entry;
| |
| ChapterURLobject = URLobject;
| |
| URLobject = create_url_object ();
| |
| end
| |
| Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
| |
| Periodical = ''; -- redundant so unset
| |
| else
| |
| if is_set (Title) or is_set (ScriptTitle) then
| |
| entry_redundant = is_set (Entry);
| |
| else
| |
| Title = Entry;
| |
| end
| |
| end
| |
| if entry_redundant then
| |
| select_one (args, {'title', 'script-title', 'article', 'entry'}, 'redundant_parameters');
| |
| end
| |
| else
| |
| Entry = discard_parameter (Entry, A:ORIGIN ('Entry'), nil);
| |
| end
| |
|
| |
| -- Special case for cite report.
| |
| local Docket = A['Docket'];
| |
| if citation_class == 'report' then
| |
| if is_set (Docket) then
| |
| if is_set (ID) then
| |
| select_one (args, {'id', 'docket'}, 'redundant_parameters');
| |
| end
| |
| ID = Docket; -- for cite report when |docket= is set, overwrite ID even if |id= is set
| |
| Docket = '';
| |
| end
| |
| elseif citation_class ~= 'thesis' then
| |
| discard_parameter (Docket, A:ORIGIN ('Docket'), '');
| |
| end
| |
| | |
| -- Special case for cite techreport.
| |
| local Num = A['Number'];
| |
| if citation_class == 'techreport' then -- special case for cite techreport
| |
| if is_set (Num) then -- cite techreport uses 'number', which other citations alias to 'issue'
| |
| if not is_set (ID) then -- can we use ID for the "number"?
| |
| ID = Num; -- yes, use it
| |
| else -- ID has a value so emit error message
| |
| select_one (args, {'id', 'number'}, 'redundant_parameters');
| |
| end
| |
| end
| |
| elseif not is_set (Issue) then
| |
| Num = discard_parameter (Num, A:ORIGIN ('Number'), nil);
| |
| end
| |
| | |
| -- special case for cite interview
| |
| local Callsign = A['Callsign'];
| |
| local City = A['City'];
| |
| local Program = A['Program'];
| |
| | |
| if (citation_class == 'interview') then
| |
| if is_set (Program) then
| |
| ID = ' ' .. Program;
| |
| end
| |
| if is_set (Callsign) then
| |
| if is_set (ID) then
| |
| ID = ID .. pend_separator (Callsign, sepc, true);
| |
| else
| |
| ID = ' ' .. Callsign;
| |
| end
| |
| end
| |
| if is_set (City) then
| |
| if is_set (ID) then
| |
| ID = ID .. pend_separator (City, sepc, true);
| |
| else
| |
| ID = ' ' .. City;
| |
| end
| |
| end
| |
| | |
| if is_set (Others) then
| |
| Others = wrap_msg ('interview', {TitleType, Others}, use_lowercase);
| |
| TitleType = '';
| |
| end
| |
| else
| |
| Callsign = discard_parameter (Callsign, A:ORIGIN ('Callsign'), nil );
| |
| City = discard_parameter (City, A:ORIGIN ('City'), nil );
| |
| Program = discard_parameter (Program, A:ORIGIN ('Program'), nil);
| |
| end
| |
|
| |
| if is_set (TitleType) then -- if type parameter is specified
| |
| TitleType = wrap_msg ('type', TitleType, use_lowercase); -- display it in parentheses
| |
| end
| |
| -- Account for the oddity that is {{cite conference}} or {{cite speech}}.
| |
| | |
| local BookTitle = A['BookTitle'];
| |
| if 'conference' == citation_class then
| |
| if is_set (BookTitle) then
| |
| ChapterURLobject = URLobject;
| |
| URLobject = create_url_object ();
| |
| TransChapter = TransTitle;
| |
| TransTitle = '';
| |
| Chapter = Title;
| |
| Title = BookTitle;
| |
| end
| |
| else
| |
| BookTitle = discard_parameter (BookTitle, A:ORIGIN ('BookTitle'), nil);
| |
| if 'speech' == citation_class then
| |
| TitleNote = discard_parameter (TitleNote, A:ORIGIN ('TitleNote'), TitleType);
| |
| -- override whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).
| |
| TitleType = ''; -- annotate the citation
| |
| else
| |
| Conference = discard_parameter (Conference, A:ORIGIN ('Conference'), '');
| |
| -- not cite conference or cite speech so make sure this is empty string
| |
| end
| |
| end
| |
| | |
| -- cite map oddities
| |
| local Cartography = A['Cartography'];
| |
| local Scale = A['Scale'];
| |
|
| |
| if citation_class == 'map' then
| |
| Chapter = A['Map'];
| |
| TransChapter = A['TransMap'];
| |
| ChapterURLobject = create_url_object (A['MapURL'], A:ORIGIN ('MapURL'), A['MapFormat'], A:ORIGIN ('MapFormat'), A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'));
| |
| Cartography = pend_separator (wrap_msg ('cartography', Cartography, use_lowercase), sepc, true);
| |
| Scale = pend_separator (Scale, sepc, true);
| |
| else
| |
| Cartography = discard_parameter (Cartography, A:ORIGIN ('Cartography'), '');
| |
| Scale = discard_parameter (Scale, A:ORIGIN ('Scale'), '');
| |
| discard_parameter (A['Map'], A:ORIGIN ('Map'), nil);
| |
| discard_parameter (A['MapURL'], A:ORIGIN ('MapURL'), nil);
| |
| discard_parameter (A['TransMap'], A:ORIGIN ('TransMap'), nil);
| |
| discard_parameter (A['MapFormat'], A:ORIGIN ('MapFormat'), nil);
| |
| discard_parameter (A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'), nil);
| |
| end
| |
| | |
| -- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.
| |
| if 'episode' == citation_class or 'serial' == citation_class then
| |
| local AirDate = A['AirDate'];
| |
| local SeriesLink = A['SeriesLink'];
| |
| local Network = A['Network'];
| |
| local Station = A['Station'];
| |
| local s, n = {}, {};
| |
| -- do common parameters first
| |
| if is_set (Network) then table.insert (n, Network); end
| |
| if is_set (Station) then table.insert (n, Station); end
| |
| ID = table.concat (n, sepc .. ' ');
| |
|
| |
| if is_set (AirDate) then
| |
| if not is_set (Date) then -- promote airdate to date
| |
| Date = AirDate;
| |
| Dateorigin = A:ORIGIN ('AirDate');
| |
| else
| |
| select_one (args, {'date', 'air-date', 'airdate'}, 'redundant_parameters');
| |
| end
| |
| end
| |
| | |
| if 'episode' == citation_class then -- handle the oddities that are strictly {{cite episode}}
| |
| local Season = A['Season'];
| |
| local SeriesNumber = A['SeriesNumber'];
| |
| | |
| if is_set (Season) and is_set (SeriesNumber) then -- these are mutually exclusive so if both are set
| |
| select_one (args, {'season', 'series-number', 'series-no', 'seriesnumber', 'seriesno'}, 'redundant_parameters');
| |
| -- add error message
| |
| SeriesNumber = ''; -- unset; prefer |season= over |seriesno=
| |
| end
| |
| -- assemble a table of parts concatenated later into Series
| |
| if is_set (Season) then table.insert (s, wrap_msg ('season', Season, use_lowercase)); end
| |
| if is_set (SeriesNumber) then table.insert (s, wrap_msg ('series', SeriesNumber, use_lowercase)); end
| |
| if is_set (Issue) then table.insert (s, wrap_msg ('episode', Issue, use_lowercase)); end
| |
| Issue = ''; -- unset because this is not a unique parameter
| |
|
| |
| Chapter = Title; -- promote title parameters to chapter
| |
| ScriptChapter = ScriptTitle;
| |
| local ChapterLink = TitleLink; -- alias episodelink
| |
| local ChapterLinkorigin = TitleLinkorigin;
| |
| TransChapter = TransTitle;
| |
| ChapterURLobject = URLobject;
| |
|
| |
| Title = Series; -- promote series to title
| |
| TitleLink = SeriesLink;
| |
| TitleLinkorigin = A:ORIGIN ('SeriesLink');
| |
| Series = table.concat (s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number
| |
| | |
| if is_set (ChapterLink) and not is_set (ChapterURL) then -- link but not URL
| |
| Chapter = make_internal_link (ChapterLink, Chapter, ChapterLinkorigin);
| |
| -- ok to wikilink
| |
| elseif is_set (ChapterLink) and is_set (ChapterURL) then -- if both are set, URL links episode;
| |
| Series = make_internal_link (ChapterLink, Series, ChapterLinkorigin);
| |
| -- series links with ChapterLink (episodelink -> TitleLink -> ChapterLink) ugly
| |
| end
| |
| URLobject = create_url_object (); -- unset
| |
| TransTitle = '';
| |
| ScriptTitle = '';
| |
|
| |
| else -- now oddities that are cite serial
| |
| Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
| |
| if is_set (Series) and is_set (SeriesLink) then
| |
| Series = make_internal_link (SeriesLink, Series, A:ORIGIN ('SeriesLink'));
| |
| end
| |
| Series = wrap_style ('italic-title', Series); -- series is italicized
| |
| end
| |
| end
| |
| -- end of {{cite episode}} stuff
| |
| | |
| -- Account for the oddities that are {{cite arxiv}}, before generation of COinS data.
| |
| if 'arxiv' == citation_class then
| |
| if not is_set (ID_list['ARXIV']) then -- |arxiv= or |eprint= required for cite arxiv
| |
| append_error ('arxiv_missing', {}); -- add error message
| |
| elseif is_set (Series) then -- series is an alias of version
| |
| ID_list['ARXIV'] = ID_list['ARXIV'] .. Series; -- concatenate version onto the end of the arxiv identifier
| |
| Series = ''; -- unset
| |
| deprecated_parameter ('version'); -- deprecated parameter but only for cite arxiv
| |
| end
| |
|
| |
| if first_set ({AccessDate, At, URLobject['format'], Page, Pages, PublisherName, URLobject['url'], -- a crude list of parameters that are not supported by cite arxiv
| |
| ID_list['ASIN'], ID_list['BIBCODE'], ID_list['DOI'], ID_list['ISBN'], ID_list['ISSN'],
| |
| ID_list['JFM'], ID_list['JSTOR'], ID_list['LCCN'], ID_list['MR'], ID_list['OCLC'], ID_list['OL'],
| |
| ID_list['OSTI'], ID_list['PMC'], ID_list['PMID'], ID_list['RFC'], ID_list['SSRN'], ID_list['USENETID'], ID_list['ZBL']},27) then
| |
| append_error ('arxiv_params_not_supported', {}); -- add error message
| |
| | |
| AccessDate= ''; -- set these to empty string; not supported in cite arXiv
| |
| PublisherName = ''; -- (if the article has been published, use cite journal, or other)
| |
| URLobject = create_url_object ();
| |
| Page = ''; Pages = ''; At = '';
| |
| end
| |
| Periodical = 'arXiv'; -- periodical not allowed in cite arxiv; if article has been published, use cite journal
| |
| -- set to arXiv for COinS; after that, must be set to empty string
| |
| end
| |
|
| |
| -- legacy: promote concatenation of |month=, and |year= to Date if Date not set; or, promote PublicationDate to Date if neither Date nor Year are set.
| |
| if not is_set (Date) then
| |
| if is_set (Year) then
| |
| Date = Year;
| |
| Dateorigin = A:ORIGIN ('Year'); -- promote Year to Date
| |
| Year = nil; -- make nil so Year as empty string isn't used for CITEREF
| |
| elseif is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set
| |
| Date = PublicationDate;
| |
| Dateorigin = A:ORIGIN ('PublicationDate'); -- promote PublicationDate to Date
| |
| PublicationDate = '';
| |
| end
| |
| else
| |
| if is_set (PublicationDate) and PublicationDate ~= Date then
| |
| PublicationDate = wrap_msg ('publication-date', PublicationDate, use_lowercase);
| |
| else
| |
| PublicationDate = ''; -- if PublicationDate is same as Date, don't display in rendered citation
| |
| end
| |
| end
| |
| | |
| local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification
| |
| local anchor_year = validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, Dateorigin);
| |
| -- used in the CITEREF identifier
| |
| | |
| -- Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set. Do this after date check but before COInS.
| |
| -- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date
| |
| Embargo = is_embargoed (Embargo); --
| |
| | |
| if citation_class == 'journal' and not is_set (URLobject['url']) and is_set (ID_list['PMC']) then
| |
| if not is_set (Embargo) then -- if not embargoed or embargo has expired
| |
| URLobject['url'] =cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed
| |
| URLobject['origin'] = cfg.id_handlers['PMC'].parameters[1]; -- set URLorigin to parameter name for use in error message if citation is missing a |title=
| |
| end
| |
| end
| |
|
| |
| if not is_set (URLobject['url']) then
| |
| if in_array (citation_class, cfg.args_support['templates_requiring_url']) then
| |
| append_error ('cite_web_url', {});
| |
| end
| |
|
| |
| -- Test if accessdate is given without giving a URL
| |
| if is_set (AccessDate) and not is_set (ChapterURLobject['url']) then -- ChapterURL may be set when the others are not set; TODO: move this to a separate test?
| |
| append_error ('accessdate_missing_url', {});
| |
| AccessDate = '';
| |
| end
| |
| end
| |
| | |
| -- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
| |
| -- Test if citation has no title
| |
| if not is_set (Title) and
| |
| not is_set (TransTitle) and
| |
| not is_set (ScriptTitle) then
| |
| if 'episode' == citation_class then -- special case for cite episode; TODO: is there a better way to do this?
| |
| append_error ('citation_missing_title', {'series'});
| |
| else
| |
| append_error ('citation_missing_title', {'title'});
| |
| end
| |
| end
| |
|
| |
| if 'none' == Title and citation_class == 'journal' then -- special case for journal cites
| |
| Title = ''; -- set title to empty string
| |
| add_maint_cat ('untitled');
| |
| end
| |
| | |
| check_for_external_link ({ -- add error message when any of these parameters contains a URL
| |
| ['title'] = Title,
| |
| [A:ORIGIN ('Chapter')] = Chapter,
| |
| [A:ORIGIN ('Periodical')] = Periodical,
| |
| [A:ORIGIN ('PublisherName')] = PublisherName,
| |
| });
| |
| | |
| -- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
| |
| -- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that
| |
| -- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title
| |
| -- is the article title, and Chapter is a section within the article. So, we remap
| |
|
| |
| local coins_chapter = Chapter; -- default assuming that remapping not required
| |
| local coins_title = Title; -- et tu
| |
| if 'encyclopaedia' == citation_class then
| |
| if is_set (Chapter) and is_set (Title) and is_set (Periodical) then -- if all are used then
| |
| coins_chapter = Title; -- remap
| |
| coins_title = Periodical;
| |
| end
| |
| end
| |
| | |
| -- this is the function call to COinS()
| |
| local OCinSoutput = COinS ({
| |
| ['Periodical'] = Periodical,
| |
| ['Encyclopedia'] = Encyclopedia,
| |
| ['Chapter'] = coins_chapter,
| |
| ['ScriptChapter'] = ScriptChapter,
| |
| ['Map'] = Map,
| |
| ['Degree'] = Degree; -- cite thesis only
| |
| ['Title'] = coins_title,
| |
| ['ScriptTitle'] = ScriptTitle,
| |
| ['PublicationPlace'] = PublicationPlace,
| |
| ['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid;
| |
| ['Season'] = COinS_date.rftssn,
| |
| ['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit?
| |
| ['Series'] = Series,
| |
| ['Volume'] = Volume,
| |
| ['Issue'] = Issue,
| |
| ['Pages'] = first_set ({Sheet, Sheets, Page, Pages, At}, 5),
| |
| ['Edition'] = Edition,
| |
| ['PublisherName'] = PublisherName,
| |
| ['URL'] = first_set ({ChapterURLobject['url'], URLobject['url']}, 2),
| |
| ['Authors'] = NameList,
| |
| ['ID_list'] = ID_list,
| |
| ['RawPage'] = this_page.prefixedText,
| |
| }, config.CitationClass);
| |
| | |
| -- Account for the oddities that are {{cite arxiv}}, AFTER generation of COinS data.
| |
| if 'arxiv' == citation_class then -- we have set rft.jtitle in COinS to arXiv, now unset so it isn't displayed
| |
| Periodical = '';
| |
| end
| |
| | |
| -- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text
| |
| if 'newsgroup' == citation_class then
| |
| if is_set (PublisherName) then
| |
| PublisherName = wrap_msg ('newsgroup', make_external_link ('news:' .. PublisherName, PublisherName, A:ORIGIN ('PublisherName')), use_lowercase);
| |
| end
| |
| end
| |
| | |
| -- Now perform various field substitutions.
| |
| -- We also add leading spaces and surrounding markup and punctuation to the
| |
| -- various parts of the citation, but only when they are non-nil.
| |
|
| |
| -- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,
| |
| -- an error message if the associated url is not set, or an empty string for concatenation
| |
| format_format ({ArchiveURLobject, ConferenceURLobject, URLobject, LayURLobject, TranscriptURLobject, ChapterURLobject});
| |
|
| |
| -- special case for chapter format so no error message or cat when chapter not supported
| |
| if format_url_access_text (URLobject, SubscriptionRequired, RegistrationRequired) then
| |
| select_one (args, {'url-access', 'urlaccess', 'registration', 'subscription'}, 'redundant_parameters');
| |
| end -- 只需其一
| |
| format_url_access_text (ChapterURLobject, nil, nil);
| |
| | |
| local OriginalURLobject; -- TODO: swap chapter and title here so that archive applies to most specific if both are set?
| |
| OriginalURLobject, URLobject, ChapterURLobject =
| |
| swap_urls (URLobject, ChapterURLobject, ArchiveURLobject, DeadURL);
| |
|
| |
| local chapter_no_quotes = false; -- default assume that we will be quoting the chapter parameter value
| |
| if is_set (Contribution) and has_contributors then -- if this is a contribution with contributor(s)
| |
| if in_array (Contribution:lower(), cfg.keywords['contribution']) then -- and a generic contribution title
| |
| chapter_no_quotes = true; -- then render it unquoted
| |
| end
| |
| end
| |
| Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURLobject, chapter_no_quotes, citation_class, TitleType, sepc);
| |
| -- Contribution is also in Chapter
| |
| -- Format main title.
| |
| Title, URLobject = format_main_title (Title, TitleLink, TitleLinkorigin, ScriptTitle, TransTitle, URLobject, no_chapter_format, citation_class, Periodical);
| |
| Place = pend_separator (wrap_msg ('written', Place, use_lowercase), sepc, false);
| |
| Conference = format_conference (Conference, ConferenceURLobject, Periodical, citation_class, sepc);
| |
| local Insource_location = format_insource_location (Page, Pages, Sheet, Sheets, At, Minutes, Time, TimeCaption, Section, Sections, Inset, citation_class, Periodical_origin, sepc, NoPP, use_lowercase);
| |
| Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc
| |
| | |
| Others = pend_separator (Others, sepc, true);
| |
| Others = pend_separator (wrap_msg ('translated', Translators, use_lowercase), sepc, true) .. Others;
| |
|
| |
| if 'speech' ~= citation_class then
| |
| TitleNote = pend_separator (TitleNote, sepc, true);
| |
| end
| |
|
| |
| Edition = wrap_msg ('edition', Edition, use_lowercase);
| |
| Series = pend_separator (Series, sepc, true);
| |
| OrigYear = wrap_msg ('orig year', OrigYear, use_lowercase);
| |
| Agency = pend_separator (Agency, sepc, true);
| |
| Volume = format_volume_issue (Volume, Issue, citation_class, Periodical_origin, sepc, use_lowercase);
| |
| | |
| ------------------------------------ totally unrelated data
| |
|
| |
| Via = wrap_msg ('via', Via, use_lowercase);
| |
| AccessDate = format_accessdate (AccessDate, sepc, use_lowercase);
| |
| ID = format_id (ID, Docket, sepc, use_lowercase);
| |
| ID_list = build_id_list (ID_list, {IdAccessLevels=ID_access_levels, DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo, Class = Class});
| |
| | |
| local URL = '';
| |
| if is_set (URLobject['url']) then
| |
| URL = ' ' .. make_external_link (URLobject['url'], nil, URLobject['origin']) .. URLobject['access-text'];
| |
| end
| |
|
| |
| local Format = URLobject['format'];
| |
| Quote = format_quote (Quote, sepc);
| |
| local Archived = format_archive (ArchiveURLobject, OriginalURLobject, ArchiveDate, DeadURL, sepc, use_lowercase);
| |
| local Lay = format_lay (LayURLobject, LayDate, LaySource, sepc, use_lowercase);
| |
| Transcript = format_external_link (Transcript, TranscriptURLobject, sepc);
| |
| local Publisher = format_publisher (PublisherName, PublicationPlace, Periodical, citation_class, sepc);
| |
| | |
| local use_in = is_set (Chapter) and (not has_contributors);
| |
| Authors, Editors, Contributors = format_people (Authors, Editors, Contributors, multiple_editors, use_in, sepc);
| |
|
| |
| -- Several of the above rely upon detecting this as nil, so do it last.
| |
| Periodical = format_periodical (Periodical, Title, TitleNote, sepc);
| |
| | |
| -- Piece all bits together at last. Here, all should be non-nil.
| |
| -- We build things this way because it is more efficient in LUA
| |
| -- not to keep reassigning to the same string variable over and over.
| |
| | |
| local tcommon;
| |
| local tcommon2; -- used for book cite when |contributor= is set
| |
|
| |
| if citation_class == 'journal' and is_set (Periodical) then
| |
| Others = pend_separator (Others, sepc, false);
| |
| tcommon = safe_join ({Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Edition, Publisher, Agency}, sepc);
| |
|
| |
| elseif contributors_valid then -- special cases for book cites where contributors are allowed
| |
| if is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc
| |
| tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2
| |
| tcommon2 = safe_join ({Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
| |
| else
| |
| tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
| |
| end
| |
| elseif 'map' == citation_class then -- special cases for cite map
| |
| if is_set (Chapter) then -- map in a book; TitleType is part of Chapter
| |
| tcommon = safe_join ({Title, Format, Edition, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
| |
| elseif is_set (Periodical) then -- map in a periodical
| |
| tcommon = safe_join ({Title, TitleType, Format, Periodical, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
| |
| else -- a sheet or stand-alone map
| |
| tcommon = safe_join ({Title, TitleType, Format, Edition, Scale, Series, Cartography, Others, Publisher}, sepc);
| |
| end
| |
|
| |
| elseif 'episode' == citation_class then -- special case for cite episode
| |
| tcommon = safe_join ({Title, TitleNote, TitleType, Series, Transcript, Edition, Publisher}, sepc);
| |
| else -- all other CS1 templates
| |
| tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
| |
| end
| |
|
| |
| if #ID_list > 0 then
| |
| ID_list = safe_join ({sepc .. ' ', table.concat (ID_list, sepc .. ' '), ID}, sepc);
| |
| else
| |
| ID_list = ID;
| |
| end
| |
|
| |
| -- LOCAL
| |
| local xDate;
| |
| if (is_set (Periodical) and is_set (Date) and
| |
| not in_array (citation_class, {'encyclopaedia', 'web'}))
| |
| or (in_array (citation_class, {'book', 'news'})) then
| |
| if in_array (citation_class, {'journal', 'citation'}) and is_set (Volume) then
| |
| xDate = safe_join ({Date .. ',' .. Volume, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
| |
| else
| |
| xDate = safe_join ({Date, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
| |
| end
| |
| Insource_location = ''
| |
| else
| |
| xDate = safe_join ({Date, PublicationDate, OrigYear, AccessDate}, sepc);
| |
| end
| |
| xDate = pend_separator (xDate, sepc, true);
| |
| -- END LOCAL
| |
| | |
| local idcommon = safe_join ({URL, xDate, ID_list, Archived, Via, Lay, Language, Quote}, sepc);
| |
| local text;
| |
| if is_set (Authors) then
| |
| if is_set (Contributors) then
| |
| text = safe_join ({Contributors, Chapter, tcommon, Authors, Place, Editors, tcommon2, Insource_location, idcommon }, sepc);
| |
| else
| |
| text = safe_join ({Authors, Chapter, Place, Editors, tcommon, Insource_location, idcommon }, sepc);
| |
| end
| |
| else
| |
| text = safe_join ({Editors, Chapter, Place, tcommon, Insource_location, idcommon}, sepc);
| |
| end
| |
|
| |
| if is_set (PostScript) and PostScript ~= sepc then
| |
| text = safe_join ({text, sepc}, sepc); --Deals with italics, spaces, etc.
| |
| text = text:sub (1, -sepc:len()-1);
| |
| end
| |
|
| |
| text = safe_join ({text, PostScript}, sepc);
| |
| | |
| -- Now enclose the whole thing in a <cite/> element
| |
| return format_citation (text, config.CitationClass, Ref, NameList, anchor_year, OCinSoutput, no_tracking_cats);
| |
| end
| |
| | |
| --[[--------------------------< V A L I D A T E >--------------------------------------------------------------
| |
| Looks for a parameter's name in the whitelist.
| |
| | |
| Parameters in the whitelist can have three values:
| |
| true - active, supported parameters
| |
| false - deprecated, supported parameters
| |
| nil - unsupported parameters
| |
|
| |
| ]]
| |
| | |
| local function validate (name)
| |
| local name = tostring (name);
| |
| local state = whitelist.basic_arguments[name];
| |
|
| |
| -- Normal arguments
| |
| if true == state then return true; end -- valid actively supported parameter
| |
| if false == state then
| |
| deprecated_parameter (name); -- parameter is deprecated but still supported
| |
| return true;
| |
| end
| |
|
| |
| -- Arguments with numbers in them
| |
| name = name:gsub ('%d+', '#'); -- replace digit(s) with # (last25 becomes last#
| |
| state = whitelist.numbered_arguments[name];
| |
| if true == state then return true; end -- valid actively supported parameter
| |
| if false == state then
| |
| deprecated_parameter (name); -- parameter is deprecated but still supported
| |
| return true;
| |
| end
| |
|
| |
| return false; -- Not supported because not found or name is set to nil
| |
| end
| |
| | |
| --[[--------------------------< C I T A T I O N >--------------------------------------------------------------
| |
| | |
| This is used by templates such as {{cite book}} to create the actual citation text.
| |
| | |
| ]]
| |
| | |
| function citation (frame)
| |
| local pframe = frame:getParent();
| |
| local module_path = 'Module:Citation/CS1/'
| |
| local module_suffix = frame:getTitle():gsub ('^Module:Citation/CS1', '');
| |
|
| |
| load_modules (module_path, module_suffix);
| |
|
| |
| local args = {};
| |
| local suggestions = {};
| |
| local error_reported = false;
| |
| | |
| local config = {};
| |
| for k, v in pairs (frame.args) do
| |
| config[k] = v;
| |
| args[k] = v;
| |
| end
| |
| | |
| local capture; -- the single supported capture when matching unknown parameters using patterns
| |
| for k, v in pairs (pframe.args) do
| |
| if v ~= '' then
| |
| if not validate (k) then
| |
| error_reported = false;
| |
| if type (k) ~= 'string' then
| |
| -- Exclude empty numbered parameters
| |
| if v:match ('%S+') ~= nil then
| |
| append_error ('text_ignored', {v});
| |
| error_reported = true;
| |
| end
| |
| elseif validate (k:lower()) then
| |
| append_error ('parameter_ignored_suggest', {k, k:lower()});
| |
| error_reported = true;
| |
| else
| |
| if nil == suggestions.suggestions then -- if this table is nil then we need to load it
| |
| suggestions = mw.loadData (module_path .. 'Suggestions' .. module_suffix);
| |
| end
| |
| for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
| |
| capture = k:match (pattern); -- the whole match if no caputre in pattern else the capture if a match
| |
| if capture then -- if the pattern matches
| |
| param = substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
| |
| append_error ('parameter_ignored_suggest', {k, param});
| |
| -- set the error message
| |
| error_reported = true;
| |
| break;
| |
| end
| |
| end
| |
| if not error_reported then -- couldn't match with a pattern, is there an expicit suggestion?
| |
| if suggestions.suggestions[k:lower()] ~= nil then
| |
| append_error ('parameter_ignored_suggest', {k, suggestions.suggestions[k:lower()]});
| |
| error_reported = true;
| |
| else
| |
| append_error ('parameter_ignored', {k});
| |
| error_reported = true;
| |
| end
| |
| end
| |
| end
| |
| end
| |
| args[k] = v;
| |
| elseif args[k] ~= nil or (k == 'postscript') then
| |
| args[k] = v;
| |
| end
| |
| end
| |
| local error_msg;
| |
| for k, v in pairs (args) do
| |
| if 'string' == type (k) then -- don't evaluate positional parameters
| |
| error_msg = has_invisible_chars (k, v);
| |
| if is_set (error_msg) then
| |
| append_error ('invisible_char', error_msg);
| |
| end
| |
| end
| |
| end
| |
| return do_citation (config, args)
| |
| end
| |
| | |
| --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
| |
| ]]
| |
| | |
| return {citation = citation};
| |