Jump to content
Wikipedia The Free Encyclopedia

Module:WPSHIPS utilities

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
Warning This Lua module is used on approximately 101,000 pages .
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.

ship_name_format

This function attempts to apply appropriate formatting to unformatted ship names. The formats supported are:

  1. <(prefix)> <name> <(disambiguator)> where:
    • <(prefix)> (optional) – one from a list of defined prefixes commonly used for ships (ARA, HMS, USS, etc.); rendered in upright font
    • <name> – the ship's proper name; rendered in italic font
    • <(disambiguator)> (optional) – typically the ship's hull or pennant number, or other disambiguator; always contained in parentheses; rendered in upright font
  2. <name> <(disambiguator)> where:
    • <name> – the ship's proper name; rendered in italic font
    • <(disambiguator)> (required) – the ship's hull or pennant number or a recognized ship-type descriptor; always contained in parentheses; rendered in upright font
      • hull and pennant numbers take two basic forms
        • uppercase letters, possibly followed by a space or hyphen, followed by digits (SSBN-659, R07, ON 688)
        • digits, possibly followed by a space or hyphen, followed by uppercase letters (401B)
  3. <nationality> <ship type> <name> <(disambiguator)> where:
    • <nationality> – one- or two- word nation name in adjectival form (Dutch, East Timorese, French, Ottoman, etc.); rendered in upright font
    • <ship type> – one from a list of one- to four-word phrases that describes a ship's type (aviso, brig sloop, landing ship medium, ship of the line); rendered in upright font
    • <name> – the ship's proper name; rendered in italic font
    • <(disambiguator)> (optional) – typically the ship's hull or pennant number, or other disambiguator; always contained in parentheses; rendered in upright font

The function will also attempt to render ship-class names when the name is in the form:

  • <name>-class <ship type> where:
    • <name> – the class' proper name; rendered in italic font according to the setting of |sclass=
    • <ship type> – a phrase that describes a ship's type; rendered in upright font

Lists

The function relies on three lists to accomplish its task. These lists are:

  1. ship_prefix_list – a list of commonly used ship prefixes initially taken from {{ship prefix}}; these are usually, but not always wholly uppercase
  2. nationality_list – a list of nation names in their adjectival form; these are always capitalized; always one or two words
  3. ship_type_list – a list ship-type descriptor phrases; these are usually, but not always wholly lowercase; always one to two words

To add to any of these lists, the form is:

['addition'] = true,

the trailing comma is important. See the instructions that accompany each list for limitations and implementation details.

Usage

The minimal form is:

{{#invoke:WPSHIPS_utilities|ship_name_format|name=}}

Parameters

The function requires one parameter and supports several optional parameters.

|name= – (required) the name to format
|dab=none – for use with |infobox caption=nodab in {{infobox ship begin}}, excludes a disambiguator from the formatted name
|sclass=2 – for use with {{DISPLAYTITLE}} and with |infobox caption=yes or |infobox caption=nodab in {{infobox ship begin}}, when the class is not named for a member of the class; causes the class name to be rendered in upright font
|adj=off – for use in ship-class articles with |infobox caption=yes or |infobox caption=nodab in {{infobox ship begin}}, formats the class name in its noun form and excludes the ship type phrase and disambiguator
|showerrs=yes – debug tool; not currently supported in any templates;

Wrapper template

  • {{Ship name format }} is a wrapper template to make it easier for editors to label ships in the main body of articles or as input to templates or modules. It supports the same parameters as the module.
  • In most cases, {{ship }} is preferred over using this wrapper template or this module.
  • It is useful to set the DISPLAYTITLE of redirects, disambiguation pages, or other pages named after ships which do not use one of the other "ships" templates such as {{Infobox ship begin }} to do this. Example: {{DISPLAYTITLE:{{ship_name_format|name={{FULLPAGENAME}}}}}}
  • Other templates and modules should not transclude this template, instead they should call the module directly.
  • Wikipedia pages should not transclude this template many times, as it may cause the page to exceed Wikipedia's template limits. Those pages should invoke the module directly.

wpsu.navsource()

This function is the driver for {{navsource}}. The function assembles an external wikilink from known fragments and positional parameter {{{1}}}. A ship name provided in positional parameter {{{2}}} is formatted using ship_name_format(). New with this implementation of {{navsource}} is the addition of |showerrs=. The {{#invoke:}} in the template defaults to |showerrs=yes which can be overridden by setting |showerrs=no in the template.

wpsu.hnsa()

Similar to {{navsource}}, this code supports {{hnsa}} by attempting to construct a link to a ship article at the Historic Naval Ships Association website.

The template has the form:

{{hnsa|<page>|<name>}}

where:

<page> is the name of the page from the url http://hnsa.org/hnsa-ships/<page>
<name> (optional) is the name of the ship; if left blank, the template uses the current page title; if a ship name, it is formatted using do_ship_name_format()

from which this code produces:

[http://hnsa.org/hnsa-ships/<page> <name>] at Historic Naval Ships Association
The above documentation is transcluded from Module:WPSHIPS utilities/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.

 require('strict')
 localget_args=require('Module:Arguments').getArgs;
 localstyles=require('Module:WPMILHIST Infobox style');-- infobox css
 localdata=mw.loadData('Module:WPSHIPS utilities/data');
 localnamespace=mw.title.getCurrentTitle().namespace;-- used for categorization


 --[[--------------------------< E R R O R _ M A P _ T >--------------------------------------------------------
 ]]

 localerror_map_t={-- [1] is error message; [2] is error category
 synonymous={'has synonymous parameter','Category:Pages using infobox ship with synonymous parameters'};
 missing={'missing required parameter: %s','Category:WPSHIPS: sclass and sclass2 errors'},
 format={'invalid format code: %s. Should be 0–5, or blank','Category:WPSHIPS: sclass and sclass2 errors'},
 missing_name={'missing name','Category:WPSHIPS: Template Ship parameter errors'},
 missing_dab={'missing disambiguator','Category:WPSHIPS: Template Ship parameter errors'},
 missing_prefix={'missing prefix','Category:WPSHIPS: Template Ship parameter errors'},
 invalid_control={'invalid control parameter: %s','Category:WPSHIPS: Template Ship parameter errors'},
 }


 --[[--------------------------< E R R O R _ M S G _ M A K E >--------------------------------------------------

 assembles an error message from message text and category in <error_map_t>. creates a help link to the category
 page; categorizes only main and template namespaces.

 <no_cat> disables categorization for those templates that support it; to disable categorization set <no_cat> true

 ]]

 localfunctionerror_msg_make(msg_idx,template,detail,no_cat,link_template_name)
 localout={};
 localcategory;

 table.insert(out,'<span style=\"font-size: 100%; font-style: normal;\" class=\"error\">Error: ');--TODO: simplify?
 iftemplatethen
 iflink_template_namethen
 table.insert(out,table.concat({'{{[[Template:',template,'|',template,']]}} '}));
 else
 table.insert(out,table.concat({'{{',template,'}} '}));-- TODO: get template names for synonymous parameter errors
 end
 end
 table.insert(out,string.format(error_map_t[msg_idx][1],detail));-- build error message from base + <detail>
 table.insert(out,table.concat({' ([[:',error_map_t[msg_idx][2],'|help]])'}));-- help text on category pages; TODO: help text on template pages also?
 table.insert(out,'</span>');

 if(0==namespaceor10==namespace)andnotno_catthen-- categorize in article space (and template space to take care of broken usages)
 table.insert(out,table.concat({'[[',error_map_t[msg_idx][2],']]'}));
 end

 returntable.concat(out);-- make a big string and done
 end


 --[[--------------------------< I S _ S E T >------------------------------------------------------------------

 Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.

 ]]

 localfunctionis_set(var)
 returnnot(var==nilorvar=='');
 end


 --[[--------------------------< S I Z E O F _ S H I P _ T Y P E >----------------------------------------------

 Returns the size in words of ship type. Inputs are the fragment table, the number of elements in the fragment table,
 and the number of words that make up nationality.

 The number of fragments (words) in a ship name dictate the possible sizes of ship type. If nationality takes one fragment,
 and ship type takes four fragments, then the minimum number of fragments in a composite ship name is:
 	5 = 1 (nationality) + 3 (ship type) + 1 (ship name) (same as 4 fragments (words) after nationality)

 This function starts at the longest possible series of fragments that might be ship type. This order is important becuase
 some ship types might begin with similar fragments: 'ship' and 'ship of the line'. Starting with the least possible
 series of fragments (1) would find 'ship' and make 'of the line' part of the italicized name.

 Returns 0 if there is no recognizable ship type.

 ]]

 localfunctionsizeof_ship_type(frag,frag_len,nat_len)
 localship_type;

 if5<=(frag_len-nat_len)then-- must have at least five fragments after nationality for four-word ship type
 ship_type=table.concat(frag,' ',nat_len+1,nat_len+4);-- four-word ship type
 ifdata.ship_type_t[ship_type]then
 return4;
 end
 end
 if4<=(frag_len-nat_len)then-- must have at least four fragments after nationality for three-word ship type
 ship_type=table.concat(frag,' ',nat_len+1,nat_len+3);-- three-word ship type
 ifdata.ship_type_t[ship_type]then
 return3;
 end
 end
 if3<=(frag_len-nat_len)then-- must have at least three fragments after nationality for two-word ship type
 ship_type=table.concat(frag,' ',nat_len+1,nat_len+2);-- two-word ship type
 ifdata.ship_type_t[ship_type]then
 return2;
 end
 end
 if2<=(frag_len-nat_len)then-- must have at least two fragments after nationality for one-word ship type
 ifdata.ship_type_t[frag[nat_len+1]]then-- one-word ship type
 return1;
 end
 end
 return0;-- no recognizable ship type
 end

 --[[--------------------------< S I Z E O F _ N A T I O N A L I T Y >------------------------------------------

 This function the size (in words) of the nationality from the fragments table. Nationality may be one or two
 words that occupy the first one or two positions in the table.

 Returns the number of words that identify the nationality:
 	1 for French or German, etc.
 	2 for United States;
 	0 when table doesn't have a recognizable nationality

 ]]

 localfunctionsizeof_nationality(frag,frag_len)
 localnat='';

 ifnotdata.nationality_t[frag[1]]then-- if not a one-word nationality
 if2<=frag_len-2then-- must have at least two fragments after nationality for minimal ship type and name
 nat=table.concat(frag,' ',1,2);
 ifdata.nationality_t[nat]then-- is it a two-word nationality?
 return2;-- yes
 else
 return0;-- no
 end
 end
 return0;-- not one-word and not enough fragments for two-word
 end
 return1;-- one-word nationality
 end


 --[[-------------------------< D O _ S H I P _ N A M E _ F O R M A T >-----------------------------------------

 This function applies correct styling to ship and ship-class names. These names are, for example, ship-article titles
 used by templates {{navsource}}, {{Infobox ship begin}}, where the article title is to be rendered with proper
 styling.

 This function requires one argument:
 	|name= (required): a name is required; if missing or empty, this function returns an error message (may or may not be visible depending on where it is used)
 		used in {{infobox ship begin}} to provide a value for {{DISPLAYTITLE:}} and to provide a value for |infobox caption=
 			{{#invoke:WPSHIPS_utilities|ship_name_format|name={{PAGENAME}}}}
 Optional arguments to support {{infobox ship begin}}:
 	|dab=none – displays ship name without parenthetical disambiguator; use when |infobox caption=nodab
 	|sclass=2 – for ship classes only; displays class name without italics (parameter name is loosely similar to {{slcass2}} which does the same thing); use when |infobox caption=class
 	|adj=off – for ship classes only; displays class name as a noun (no hyphen, no ship type); use when |infobox caption=class

 Arguments are passed in a table.

 to call this function locally:
 	do_ship_name_format ({['name=name'], ['dab']=dab, ['sclass']=sclass, ['adj']=adj, ['showerrs']=showerrs}) or
 	args = {['name=name'], ['dab']=dab, ['sclass']=sclass, ['adj']=adj, ['showerrs']=showerrs};
 	do_ship_name_format (args)

 The function returns the formatted name or, if unable to format the name, the original name and an unformatted error message.

 ]]

 localfunctiondo_ship_name_format(args)
 localname_sans_dab;-- the ship or class name without a trailing parenthetical dab
 localdab;-- the dab stripped from the name
 localfragments={};-- a table of words that make up name_sans_dab
 localship_type;-- a word or phrase that describes a ship
 localtype_len;-- the number of words that describe a ship
 localnat_len;-- the number of words used to specify a ship's nationality
 localname='';-- the reassembles and formatted ship name
 localerror_msg='';-- a repository for error messages if any

 --	args.name = mw.text.decode (args.name);										-- replace html entities in title with their characters; doesn't work for &amp; and &#38; in prefix
 args.name=args.name:gsub("&#39;","\'");-- replace html appostrophe with the character
 --	args.name = args.name:gsub ("&amp;", "&");
 --	args.name = args.name:gsub ("&#38;", "&");
 --	args.name = args.name:gsub ("&amp;", "&#38;");


 ifargs.name:match('.+%-class%s+%a+')then-- if a ship-class
 fragments=mw.text.split(args.name,'-class');-- split at -class
 if'2'==args.sclassthen-- for DISPLAYTITLE and infobox caption when class not named for a member of the class
 if'off'==args.adjthen
 returnfragments[1]..' class';-- for infobox caption do noun form <name> class (no hyphen, no ship type)
 end
 returnargs.name;-- nothing to do so return original unformatted name
 end
 if'off'==args.adjthen
 return"''"..fragments[1].."'' class";-- for infobox caption do noun form <name> class (no hyphen, no ship type)
 end
 return"''"..fragments[1].."''-class"..fragments[2];-- and return formatted adjectival name
 end
 -- not a ship class so try to format a ship name
 name_sans_dab,dab=args.name:match('^(.+)%s+(%b())%s*$');-- split name into name_sans_dab and dab
 ifis_set(dab)then
 dab=' '..dab;-- insert a space for later reassembly
 else
 name_sans_dab=args.name;-- because without a dab, the string.match returns nil
 dab='';-- empty string for concatenation
 end

 fragments=mw.text.split(name_sans_dab,'%s');-- split into a table of separate words

 nat_len=sizeof_nationality(fragments,#fragments);-- get the number of words in the ship's nationality
 if0<nat_lenthen-- if not zero we have a valid nationality
 type_len=sizeof_ship_type(fragments,#fragments,nat_len);-- get the number of words in the ship type
 if0<type_lenthen-- if not zero, ship type is valid; nationality and type not italics, the rest is name
 name="''"..table.concat(fragments,' ',nat_len+type_len+1).."''";-- format name
 if'none'==args.dabthen-- for |infobox caption=nodab
 returnname;-- return the formatted name without the nationality or ship type or dab
 end
 name=table.concat(fragments,' ',1,nat_len+type_len).." "..name;-- assemble everything but dab
 else
 error_msg=' unrecognized ship type;';-- valid nationality, invalid ship type
 end
 elseifdata.ship_prefix_t[fragments[1]]then-- if the first fragment is a ship prefix
 name=table.remove(fragments,1);-- fetch it from the table
 name=name.." ''"..table.concat(fragments,' ').."''";-- assemble formatted name
 else
 error_msg=' no nationality or prefix;';-- invalid nationality and first word in ship name not a valid prefix
 end

 ifis_set(name)then-- name will be set if we were able to format it
 if'none'==args.dabthen-- for |infobox caption=nodab
 returnname;-- return the formatted name without the dab
 end
 returnname..dab;-- return the formatted name with the dab
 end

 ifis_set(dab)then
 ifdab:match('%(%u+[%- ]?%d+%)')or-- one or more uppercase letters, optional space or hyphen, one or more digits
 dab:match('%(%d+[%- ]?%u+%)')or-- one or more digits, optional space or hyphen, one or more uppercase letters
 dab:match('%(%u[%u%-]*%-%d+%)')or-- one or more uppercase letters with hyphens, a hyphen, one or more digits (e.g., T-AO-157)
 dab:match('%([12]%d%d%d%)')then-- four digits representing year in the range 1000–2999
 name="''"..table.concat(fragments,' ').."''";-- format the name
 if'none'==args.dabthen-- for |infobox caption=nodab
 returnname;-- return the formatted name without the dab
 end
 returnname..dab;-- return the formatted name with the dab
 end
 -- last chance, is there a ship type in the dab?
 forkey,_inpairs(data.ship_type_t)do-- spin through the ship type list and see if there is a ship type (key) in the dab
 ifdab:find('%f[%a]'..key..'%f[^%a]')then-- avoid matches that are not whole word
 name="''"..table.concat(fragments,' ').."''";-- format the name
 if'none'==args.dabthen-- for |infobox caption=nodab
 returnname;-- return the formatted name without the dab
 end
 returnname..dab;-- return the formatted name with the dab
 end
 end
 error_msg=error_msg..' no ship type in dab;';

 if'none'==args.dabthen-- for |infobox caption=nodab
 returntable.concat(fragments,' '),error_msg;-- return the unformatted name without the dab, and an error message
 end
 end

 returnargs.name,error_msg;-- return original un-formatted name with unformatted error message if any
 end


 --[[-------------------------< S H I P _ N A M E _ F O R M A T >-----------------------------------------------

 This function is the external interface to do_ship_name_format().

 The function requires one parameter:
 	|name= (required): a name is required; if missing or empty, this function returns an error message (may or may not be visible depending on where it is used)
 		used in {{infobox ship begin}} to provide a value for {{DISPLAYTITLE:}} and to provide a value for |infobox caption=
 			{{#invoke:WPSHIPS_utilities|ship_name_format|name={{PAGENAME}}}}
 Optional parameters to support {{infobox ship begin}}:
 	|dab=none – displays ship name without parenthetical disambiguator; use when |infobox caption=nodab
 	|sclass=2 – for ship classes only; displays class name without italics (parameter name is loosely similar to {{slcass2}} which does the same thing); use when |infobox caption=class
 	|adj=off – for ship classes only; displays class name as a noun (no hyphen, no ship type); use when |infobox caption=class
 Other optional parameters:
 	|showerrs=yes – marginally useful; can display error messages if the module invocation is not buried in a template

 Values from the above parameters are placed in a table and that table passed as an argument in the call to do_ship_name_format().

 do_ship_name_format() returns two strings: a name and an error message. If do_ship_name_format() could format the name, it returns the formatted name and 
 an empty string for the error message. If it could not format the name, do_ship_name_format() returns the original name and an error message.

 Formatting of the error message, in response to |showerrs=yes is the responsibility of the calling function.

 ]]

 localfunctionship_name_format(frame)
 localname='';-- destination of the formatted ship name
 localerror_msg='';-- destination of any error message

 ifnotis_set(frame.args.name)then-- if a ship name not provided
 if'yes'==frame.args.showerrsthen-- and we're supposed to show errors
 error_msg='<span style="font-size:100%; font-weight:normal" class="error">Empty name</span>';-- return an empty string error message if there is no name
 end
 else
 name,error_msg=do_ship_name_format(frame.args);-- get formatted name and error message
 ifis_set(error_msg)and'yes'==frame.args.showerrsthen-- if appropriate, show error message
 error_msg='<span style="font-size:100%; font-weight:normal" class="error">'..error_msg..'</span>';
 else
 error_msg='';-- for concatenation
 end
 end

 returnname..error_msg;-- return name and error message
 end


 --[[--------------------------< H N S A >----------------------------------------------------------------------

 Similar to {{navsource}}, this code supports {{hnsa}} by attempting to construct a link to a ship article at the
 the Historic Nava Ships Association website.

 The template has the form:
 	{{hnsa|<page>|<name>}}
 where:
 	<page> is the name of the page at http://hnsa.org/hnsa-ships/<page>
 	<name> (optional) is the name of the ship; if left blank, the template uses the current page title; if a ship name, it is formatted
 from which this code produces:
 	[http://hnsa.org/hnsa-ships/<page> <name>] at Historic Naval Ships Association

 ]]

 localfunctionhnsa(frame)
 localpframe=frame:getParent()-- get arguments from calling template frame
 localship_name='';
 localerror_msg='';
 localarticle_title=mw.title.getCurrentTitle().text;-- fetch the article title

 ifnotis_set(pframe.args[1])then
 return'<span style="font-size:100%; font-weight:normal" class="error">missing hsna page</span>';
 end

 localfmt_params={['name']='',['showerrs']=nil};

 ifis_set(pframe.args.showerrs)then-- if showerrs set in template, override showerrs in #invoke:
 fmt_params.showerrs=pframe.args.showerrs;-- template value
 else
 fmt_params.showerrs=frame.args.showerrs;-- invoke value
 end

 ifis_set(pframe.args[2])then
 fmt_params.name=pframe.args[2];
 else
 fmt_params.name=article_title;-- use article title
 end

 ship_name,error_msg=do_ship_name_format(fmt_params);

 ifis_set(error_msg)andis_set(pframe.args[2])then-- if unable to format the name
 localescaped_name=pframe.args[2]:gsub("([%(%)%.%-])","%%%1");-- escape some of the Lua magic characters
 ifpframe.args[2]==article_titleor-- is name same as article title?
 nil~=article_title:find('%f[%a]'..escaped_name..'%f[%s]')or-- is name a word or words substring of article title?
 nil~=article_title:find('%f[%a]'..escaped_name..'$')then-- is name a word or words substring that ends article title?
 ship_name="''"..pframe.args[2].."''";-- non-standard 'name'; perhaps just the name without prefix and dab;
 error_msg='';-- unset because we think we have a name
 end
 end
 ifis_set(error_msg)and'yes'==fmt_params.showerrsthen
 error_msg='<span style="font-size:100%; font-weight:normal" class="error">'..error_msg..'</span>';
 else
 error_msg='';-- unset so it doesn't diplay
 end

 localoutput={
 '[http://www.hnsa.org/hnsa-ships/',
 pframe.args[1],
 '/ ',
 ship_name,
 '] at Historic Naval Ships Association',
 error_msg,
 }

 returntable.concat(output);
 end


 --[[--------------------------< N A V S O U R C E >------------------------------------------------------------

 This version of the template {{navsource}} was added as a test vehicle for do_ship_name_format().

 ]]

 localfunctionnavsource(frame)
 localpframe=frame:getParent()-- get arguments from calling template frame
 localship_name='';
 localerror_msg='';
 localarticle_title=mw.title.getCurrentTitle().text;-- fetch the article title

 ifnotis_set(pframe.args[1])then
 return'<span style="font-size:100%; font-weight:normal" class="error">missing navsource URLcode</span>';
 end

 localfmt_params={['name']='',['showerrs']=nil};

 ifis_set(pframe.args.showerrs)then-- if showerrs set in template, override showerrs in #invoke:
 fmt_params.showerrs=pframe.args.showerrs;-- template value
 else
 fmt_params.showerrs=frame.args.showerrs;-- invoke value
 end

 ifis_set(pframe.args[2])then
 fmt_params.name=pframe.args[2];
 else
 fmt_params.name=article_title;-- use article title
 end

 ship_name,error_msg=do_ship_name_format(fmt_params);

 ifis_set(error_msg)andis_set(pframe.args[2])then-- if unable to format the name
 localescaped_name=pframe.args[2]:gsub("([%(%)%.%-])","%%%1");-- escape some of the Lua magic characters
 ifpframe.args[2]==article_titleor-- is name same as article title?
 nil~=article_title:find('%f[%a]'..escaped_name..'%f[%s]')or-- is name a word or words substring of article title?
 nil~=article_title:find('%f[%a]'..escaped_name..'$')then-- is name a word or words substring that ends article title?
 ship_name="''"..pframe.args[2].."''";-- non-standard 'name'; perhaps just the name without prefix and dab;
 error_msg='';-- unset because we think we have a name
 end
 end
 ifis_set(error_msg)and'yes'==fmt_params.showerrsthen
 error_msg='<span style="font-size:100%; font-weight:normal" class="error">'..error_msg..'</span>';
 else
 error_msg='';-- unset so it doesn't diplay
 end

 localoutput={
 '[http://www.navsource.net/archives/',
 pframe.args[1],
 '.htm Photo gallery] of ',
 ship_name,
 ' at NavSource Naval History',
 error_msg,
 }

 returntable.concat(output);
 end


 --[[--------------------------< _ S H I P >--------------------------------------------------------------------

 This is a possible replacement for the template {{ship}}. It has better error detection and handling.

 ]]

 localfunction_ship(prefix,name,dab,control,unlinked_prefix,unlinked_whole,template,no_cat)
 localerror_msg='';
 localcategory='';

 ifnotis_set(control)then
 control='';-- if not provided, ensure that control is empty string for comparisons
 elseifcontrol:find('%-')then-- shortcut for |link=no when using a format control parameter ...|SSBN-659|-6}} same as ...|SSBN-659|6|link=no}}
 unlinked_whole=true;-- set the unlinked flag
 control=control:match('%d');-- strip out the hyphen
 end

 -- dispose of error conditions straight away
 ifnotis_set(name)then-- this is the only required parameter
 error_msg=error_msg_make('missing_name',template,'',no_cat,true);
 elseifnotis_set(dab)and('1'==controlor'3'==controlor'5'==control)then-- dab required when control value set to expect it
 error_msg=error_msg_make('missing_dab',template,'',no_cat,true);
 elseifnotis_set(prefix)and('5'==controlor'6'==control)then-- prefix required when control value set to expect it
 error_msg=error_msg_make('missing_prefix',template,'',no_cat,true);
 elseif'4'==controlthen-- displaying only the prefix
 error_msg=error_msg_make('invalid_control',template,control,no_cat,true);
 elseifis_set(control)then
 if('number'~=type(tonumber(control)))or(1~=control:len())or(1>tonumber(control)or6<tonumber(control))then-- control must be a single-digit number 1 through 6
 error_msg=error_msg_make('invalid_control',template,control,no_cat,true);
 end
 elseifnotis_set(prefix)andunlinked_prefixthen-- prefix required when |up=yes
 error_msg=error_msg_make('missing_prefix',template,'',no_cat,true);
 end

 ifis_set(error_msg)then
 returnerror_msg;
 end

 locallink_name;
 locallink='';

 ifis_set(prefix)then
 link=prefix..' '..name;-- begin assembling the article name (link) portion of the wikilink
 else
 link=name;
 end

 ifis_set(dab)then
 link=link..' ('..dab..')';-- wrap dab in parentheses
 end

 localtarget_object=mw.title.new(link).redirectTarget;-- if <link> points to a redirect
 iftarget_objectthen
 link=target_object.fullText;-- get the target title to avoid linking through the redirect
 end

 name="''"..name.."''";-- name is always italicized so do it now

 if'1'==controlthen
 link_name=dab;-- special case when displaying only the dab, don't wrap in parentheses
 end

 ifis_set(dab)then-- for all other cases that display dab
 if'5'==controlthen
 dab="&nbsp;\'\'"..dab.."\'\'";-- for prefix with dab display HMS A1. italicize the dab
 else
 dab='&nbsp;('..dab..')';-- except for dab-only, all others display with parentheses 
 end
 end

 ifnotis_set(control)then-- when control not set: prefix, name, and dab
 ifis_set(prefix)then
 link_name=prefix..'&nbsp;'..name..dab;
 else
 link_name=name..dab;
 end
 else-- when control is not 1 or none
 if'2'==controlthen-- name only
 link_name=name;
 elseif'3'==controlthen-- name and dab
 link_name=name..dab;
 elseif'5'==controlthen-- prefix and dab
 link_name=prefix..dab;
 elseif'6'==controlthen-- prefix and name
 link_name=prefix..'&nbsp;'..name;
 end
 end

 if'5'~=controland'6'~=controlandis_set(control)then
 unlinked_prefix=false;-- no prefix so don't try to unlink it
 end

 ifunlinked_wholethen
 returnlink_name;-- no linking desired so done
 elseifunlinked_prefixandis_set(prefix)then-- when there is a prefix to unlink
 link_name=link_name:gsub('^.-&nbsp;','',1);-- remove the prefix and nbsp
 returnprefix..'&nbsp;[['..link..'|'..link_name..']]';-- add prefix and nbsp to front and done
 else
 return'[['..link..'|'..link_name..']]';-- construct the wikilink and done
 end
 end


 --[[--------------------------< S H I P >----------------------------------------------------------------------

 This is a possible replacement for the template {{ship}}. It has better error detection and handling.

 This function is the externally accessible entry point for template {{ship}}, {{HMS}}, {{USS}}, etc

 {{#invoke:WPSHIPS_utilities|ship|_template=<template name>}}

 {{#invoke:WPSHIPS_utilities|ship_pre|prefix=<prefix>|_template=<template name>}}

 Parameters in the module frame are:
 	there are no module frame parameters

 Parameters in the template frame are:
 	{{{1|}}} – prefix (HMS, USS, Japanese submarine, etc)
 	{{{2|}}} – ship's name (required)
 	{{{3|}}} – disambiguator (year, hull or pennant number, etc)
 	{{{4|}}} – format control (1, 2, 3, 5, 6; 4 not allowed)
 	|wl= – when set to 'no', rendering is not wikilinked
 	|up= – when set to 'yes' prefix (if rendered) is not linked

 ]]

 localfunctionship(frame)-- this version not supported from the template yet
 localargs_t=get_args(frame);

 localprefix=args_t[1]or'';-- fetch positional parameters into named variables for readability
 localname=args_t[2]or'';-- stripped of leading and trailing whitespace 
 localdab=args_t[3]or'';-- empty positional parameters are nil so convert nil to empty string
 localcontrol=args_t[4];
 localunlinked_prefix='yes'==args_t.up;-- make boolean: true when |up=yes
 localunlinked_whole='no'==args_t.wl;-- make boolean: true when |wl=no
 localno_cat='yes'==args_t['no-tracking'];-- make boolean: true when |no-tracking=yes

 return_ship(prefix,name,dab,control,unlinked_prefix,unlinked_whole,'Ship',no_cat);
 end


 --[[--------------------------< S H I P _ P R E F I X _ T E M P L A T E S >------------------------------------

 This is a possible replacement for the template prefix templates {{USS}}, {{HMS}}, etc. It has better error
 detection and handling.

 This function is the externally accessible entry point for those templates

 {{#invoke:WPSHIPS_utilities|ship_prefix_templates|prefix=<prefix>|template=<template name>}}

 Parameters in the module frame are:
 	|_prefix= – (required) _prefix (HMS, USS, Japanese submarine, etc)
 	|_template= template name for error messages; optional when |prefix= same as template name

 Parameters in the template frame are:
 	{{{1|}}} – ship's name (required)
 	{{{2|}}} – disambiguator (year, hull or pennant number, etc)
 	{{{3|}}} – format control (1, 2, 3, 5, 6; 4 not allowed)
 	|wl= – when set to 'no', rendering is not wikilinked
 	|up= – when set to 'yes' prefix (if rendered) is not linked

 ]]

 localfunctionship_prefix_templates(frame)-- this version not supported from the templates yet
 localargs_t=get_args(frame);

 localprefix=args_t.prefixor'';-- fetch positional parameters into named variables for readability
 localname=args_t[1]or'';-- stripped of leading and trailing whitespace 
 localdab=args_t[2]or'';-- empty positional parameters are nil so convert nil to empty string
 localcontrol=args_t[3];
 localunlinked_prefix='yes'==args_t.up;-- make boolean: true when |up=yes
 localunlinked_whole='no'==args_t.wl;-- make boolean: true when |wl=no
 localno_cat='yes'==args_t['no-tracking'];-- make boolean: true when |no-tracking=yes

 return_ship(prefix,name,dab,control,unlinked_prefix,unlinked_whole,args_t.template_nameorprefix,no_cat);
 end


 --[[--------------------------< L I S T _ E R R O R >----------------------------------------------------------

 Assembles an error message, the original parameter value and, if appropriate a category. The error message precedes
 the existing value of the parameter. If the first non-whitespace character in the parameter is a '*', set prefix to
 a '*' and sep to '\n'. For line-break lists, set prefix to empty string and sep to '<br />'.

 Category is appended to the end of the returned value only for pages in article space.

 Inputs:
 	prefix – a string of characters that precede the error message span; typically '' and '*'
 	message – the error message to be displayed; goes inside the span
 	sep – a string of characters that separates the span from the parameter value; typically '\n' and '<br />'
 	param_val – the unmodified parameter value
 	showerrs – a boolean, true to display the error message text

 ]]

 localfunctionlist_error(prefix,message,sep,param_val,showerrs)
 localerr_msg='%s<span style="font-size:100%%" class="error">list error: %s ([[:Category:WPSHIPS:Infobox list errors|help]])</span>%s%s%s';
 localcategory='';

 if0==mw.title.getCurrentTitle().namespacethen-- only categorize pages in article space
 category='[[Category:WPSHIPS:Infobox list errors]]';
 end
 iftrue==showerrsthen
 returnstring.format(err_msg,prefix,message,sep,param_val,category);-- put it all together
 else
 returnparam_val..category;
 end
 end


 --[[--------------------------< U N B U L L E T E D _ L I S T >------------------------------------------------

 Mediawiki:Common.css imposes limitations on plain, unbulleted lists. The template {{plainlist}} does not render this correctly:
 {{plainlist|
 *Item 1
 *Item 2
 **Item 2a
 ***Item 2a1
 **Item 2b
 *Item 3}}
 The above renders without proper indents for items marked ** and ***.

 If the list is not wrapped in {{plainlist}} then the above list is rendered with bullets which is contrary to the Infobox ship usage guide.

 This code translates a bulleted list into an html unordered list:

 <ul style="list-style:none; margin:0;"> 
  <li>Name 1</li>
  <li>Name 2</li>
  <ul style="list-style:none">
  <li>Subname 2a</li>
  <ul style="list-style:none">
  <li>Subname 2a1</li>
  </ul>
  <li>Subname 2b</li>
  </ul>
  <li>Name 3</li>
 </ul>

 There are rules:
 	1. The parameter value must begin with a splat but may have leading and trailing whitespace.
 	2. Each list item after the first must begin on a new line just as is required by normal bulleted lists.
 	3. When adding a sublevel, the number of splats may increase by one and never more. This is illegal:
 		*item
 		***item
 When any of these rules are violated, unbulleted_list() returns the original text and adds the article
 to Category:WPSHIPS:Infobox list errors. Error messaging in this function is somewhat sketchy so they are
 disabled. After initial adoption, better error messaging could/should be implemented.

 This function receives the content of one parameter:
 	{{#invoke:WPSHIPS utilities|unbulleted_list|{{{param|}}}}}

 ]]

 localfunction_unbulleted_list(param)
 localshowerrs=true;-- set to false to hide error messages
 localList_item_otag='<li style="padding-left: .4em; text-indent: -.4em;">';-- hanging indent markup; everything moves right with padding-left; first line moved left by neg indent

 ifnil==param:match('^%s*%*')then-- parameter value must begin with a splat (ignoring leading white space)
 ifparam:match('<[%s/]*[Bb][Rr][%s/]*>')then-- if the parameter value has a list using variants of <br /> tag
 returnlist_error('','&lt;br /> list','<br />',param,showerrs);-- return an error message with maintenance category
 elseifparam:match('<div style="clear:')then
 returnlist_error('','{{clear}} list','<br />',param,showerrs);-- return an error message with maintenance category
 elseifparam:match('.+\n%*')then-- if the parameter value has text followed by an unordered list
 returnlist_error('','mixed text and list','<br />',param,showerrs);-- return an error message with maintenance category
 end
 returnparam;-- return the parameter as is
 end

 localitem_table=mw.text.split(mw.text.trim(param),'\n');-- trim white space from end then make a table of bulleted items by splitting on newlines
 if1==#item_tablethen-- if only one bulleted item, no need for a list
 return(item_table[1]:gsub('^%*%s*',''));-- trim off the splat and any following white space and done
 end

 ifitem_table[1]:match('^%*%*+')then-- if first list item uses more than one splat, that's an error
 returnlist_error('*','too many * at start of list','\n',param,showerrs);-- return an error message with maintenance category
 end

 localhtml_table={};-- table to hold the html output
 locallevel=1;-- used to indicate when a new <ul> is required
 localsplats=0;-- number of splats that start each item in the list
 localitem='';-- the item text

 table.insert(html_table,'<ul style="list-style:none; margin:0;">')-- this for first <ul> tag; sets no bullets and no indent

 for_,vinipairs(item_table)do
 splats,item=v:match('(%*+)%s*(.*)');-- split the item into splats and item text
 ifnil==splatsthen-- nil if there is an extra line between items
 returnlist_error('*','list item missing markup','\n',param,showerrs);-- return an error message with maintenance category
 elseif''==itemthen
 returnlist_error('*','empty list item','\n',param,showerrs);-- return an error message with maintenance category
 elseifitem:match('^[;:]')then-- if the list item is mixed unordered list / description list markup (*:)
 returnlist_error('*','mixed list type','\n',param,showerrs);-- return an error message with maintenance category
 end

 splats=splats:len();-- change string of splats into a number indicating how many splats there are

 ifsplats==levelthen-- if at the same level as previous item
 table.insert(html_table,List_item_otag..item..'</li>');
 elseifsplats==level+1then-- number of splats can only increase by one
 level=splats;-- record the new level
 table.insert(html_table,'<ul style="list-style: none">');-- add a new sublist
 table.insert(html_table,List_item_otag..item..'</li>');-- and the item
 elseifsplats<levelthen-- from three splats to one splat for example
 whilesplats<leveldo
 table.insert(html_table,'</ul>');-- close each sub <ul> until level and splats match
 level=level-1;
 end
 table.insert(html_table,List_item_otag..item..'</li>');-- add the item
 else-- jumping more than one level up – one splat to three splats for example – is an error
 returnlist_error('*','too many asterisks','\n',param,showerrs);-- return an error message with maintenance category
 end
 end

 while0<leveldo
 table.insert(html_table,'</ul>');-- close each <ul> until level counted down to zero
 level=level-1;
 end

 returntable.concat(html_table,'\n');-- return the list as a string
 end


 --[[--------------------------< U N B U L L E T E D _ L I S T >------------------------------------------------

 external entry point

 ]]

 localfunctionunbulleted_list(frame)
 return_unbulleted_list(frame.args[1])
 end


 --[=[-------------------------< _I N F O B O X _ S H I P _ F L A G >--------------------------------------------

 Output of {{shipboxflag|USA}}:
 	[[File:Flag of the United States.svg|100x35px|alt=|link=]]

 Image syntax:
 	[[File:Name|Type|Border|Location|Alignment|Size|link=Link|alt=Alt|Caption]]

 This function standardizes the size of flag images in the infobox ship career header by simply overwriting the Size
 parameter value in the Image wikilink with |100x28px. This size leave a 1px gap between the top and bottom of the flag image and
 the header edge. A similar left-side gap of 2px is supplied by {{infobox ship career}}.

 ]=]

 localfunction_infobox_ship_flag(image)
 ifimage:match('|[%s%dx]+px%s*')then-- is there a size positional parameter?
 image=image:gsub('|[%s%dx]+px%s*','%|100x28px');-- overwrite it with |100x28px
 else
 return'<span style="font-size:100%" class="error">malformed flag image</span>'
 end
 returnimage;-- return the modified image
 end


 --[=[-------------------------< I N F O B O X _ S H I P _ F L A G >--------------------------------------------

 external entry point

 ]=]

 localfunctioninfobox_ship_flag(frame)
 ifnotis_set(frame.args[1])then-- if |Ship flag= not set
 return'';-- return empty string
 end

 return_infobox_ship_flag(frame.args[1]);-- return the modified image
 end


 --[=[-------------------------< C I T E _ D A N F S _ T I T L E >----------------------------------------------

 This function attempts to render a DANFS article title in more or less proper (per Wikipedia) format for the
 template {{cite danfs}}. DANFS titles typically take one of four forms:
 	<ship name> <disambiguator> <hull number>
 	<ship name> <hull number>
 	<ship name> <disambiguator>
 	<ship name>

 Here, we extract the various parts, italicize the ship name and reassemble for use by the cite danfs |title= parameter.
 To call this function:
 	|title={{#invoke:WPSHIPS utilities|cite_danfs_title|{{{title}}}}}

 ]=]

 localfunctioncite_danfs_title(frame)
 localname;
 localdisambiguator;
 localhullnum;

 ifnotis_set(frame.args[1])then-- if |title= not set
 return'';-- return empty string
 end

 name,disambiguator,hullnum=frame.args[1]:match('(.-)( [XVI]+)( %([^%)]+%))$');
 ifnot(nameanddisambiguatorandhullnum)then
 disambiguator='';-- empty string for concatenation
 name,hullnum=frame.args[1]:match('(.-)( %([^%)]+%))$');
 ifnot(nameandhullnum)then
 hullnum='';-- empty string for concatenation
 name,disambiguator=frame.args[1]:match('(.-)( [XVI]+)$');
 ifnot(nameanddisambiguator)then
 disambiguator='';
 name=frame.args[1];-- just a name or something we don't recognize
 end
 end
 end

 returntable.concat({"''",name,"''",disambiguator,hullnum});-- reassemble and done
 end


 --[[--------------------------< S Y N O N Y M _ C H E C K >----------------------------------------------------

 support function for infoboxen functions

 there are a handful of infoboxen parameters that are synonymous pairs. This function is called to see if both
 of the parameters in a synonymous pair have been assigned a value. When both have assigned values, each gets an
 error message appended to it. Most of the synonymous pairs are UK Emglish v US English so the variable names

 <args_t> table of template parameters and values
 <uk_param> UK English parameter name
 <us_param> US English parameter name
 <error_flag> boolean that this function sets true when both of a pair are set; controls addition of maint category

 ]]

 localfunctionsynonym_check(args_t,uk_param,us_param,error_flag)
 ifargs_t[uk_param]andargs_t[us_param]then

 args_t[uk_param]=args_t[uk_param]..' '..error_msg_make('synonymous');-- both are set so append error message with category
 args_t[us_param]=args_t[us_param]..' '..error_msg_make('synonymous',nil,nil,true);-- but append error message without category
 returntrue;-- inform the calling function that it needs to emit maint category
 end
 returnerror_flag;-- no match so return unmodified <error_flag>
 end

 --[[--------------------------< L I N E _ I T E M S >----------------------------------------------------------

 support function for infoboxen functions

 This function handles all infobox ship parameters that are 'line items' (label followed by value) because all
 of these sorts of parameters are rendered with exacty the same formatting.

 params_t{} is a table of tables where the params_t{} keys are the template's parameter names. The params_t{}
 values are sequences where [1] is an index number that defines where in the rendering the label/value pair is
 positioned and [2] is the label that will be rendered when the parameter has a value.

 This indexing is used because params_t{} is not a sequence and because pairs() does not necessarily return the
 'next' k/v pair.

 This function spins through params_t{} and writes html for parameters that have assigned values into temp_t{}
 according to the 'index' value in the associated sequance table. When parameters are missing or empty, this
 function writes an empty string into the associated location in lines_t{} so that lines_t{} can be concatenated
 into a string value that is returned to the calling function.

 args_t is the arguments table from the template frame.

 ]]

 localfunctionline_items(args_t,params_t)
 locallines_t={};-- a sequence table of rendered label/value html lines; one for each key in params_t{}

 fork,vinpairs(params_t)do-- k is templat e parameter name; v is a sequence table with index and associated label
 localtemp_t={}-- initialize/reinitialize for next line item
 ifnotargs_t[k]then-- if no assigned value then
 lines_t[v[1]]='';-- set to empty string for concatenation
 else
 table.insert(temp_t,'<tr style="vertical-align:top;"><td style="font-weight: bold">');-- open the line item row and cell
 table.insert(temp_t,v[2]);-- add parameter's label text
 table.insert(temp_t,'</td><td>');-- close that cell and open the parameter value cell
 table.insert(temp_t,_unbulleted_list(args_t[k]));-- add the parameter's value; formatted as unordered list if appropriate
 table.insert(temp_t,'</td></tr>\n');-- close that cell and this row
 end
 lines_t[v[1]]=table.concat(temp_t);-- concatenate and put the line item in the lines sequence table at the index position
 end

 returntable.concat(lines_t);-- make a big string of line items and done

 end


 --[[--------------------------< I S _ E M P T Y _ I B O X _ T E M P L A T E >----------------------------------

 temporary(?) code to add Category:WPSHIPS: articles with empty infobox templates when empty infobox templates
 are encountered. A template is empty when no parameters have assigned values or when the only parameter with an
 assigned value is |Hide header=

 when 'empty', returns the category name; nil else

 ]]

 localfunctionis_empty_ibox_template(args_t)
 locali=0;
 fork,vinpairs(args_t)do
 i=i+1;
 end
 if((1==i)andargs_t['Hide header'])or(0==i)then
 return'[[Category:WPSHIPS: articles with empty infobox templates]]';
 end
 end


 --[[--------------------------< I N F O B O X _ S H I P _ C A R E E R >----------------------------------------

 implements {{Infobox ship career}}

 {{#invoke:WPSHIPS utilities|infobox_ship_career}}

 ]]

 localfunctioninfobox_ship_career(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the template call

 localerr_cat=is_empty_ibox_template(args_t);-- look for and identify empty templates
 iferr_catthen
 returnerr_cat;-- template is empty so return the category and done
 end

 localhtml_out_t={};-- html table text goes here
 localerror_flag=false;-- controls emission of maint category when synonymous parameters are both set

 args_t['Hide header']=args_t['Hide header']andargs_t['Hide header']:lower();-- set to lowercase if set

 error_flag=synonym_check(args_t,'Ship stricken','Ship struck',error_flag);-- error if both synonymous parameters set
 error_flag=synonym_check(args_t,'Ship honours','Ship honors',error_flag);

 if'yes'~=args_t['Hide header']then-- |Hide header=yes then no header
 ifnot('title'==args_t['Hide header'])then-- |Hide header=title then no title bar
 table.insert(html_out_t,'<tr><th colspan="2" ');
 table.insert(html_out_t,styles.header_bar);-- style from WPMILHIST
 table.insert(html_out_t,'>History</th></tr>\n');
 end

 ifargs_t['Ship country']andargs_t['Ship flag']then
 table.insert(html_out_t,'<tr><th height="30" colspan="2" style="background-color:#B0C4DE;color:inherit;text-align:left;padding-left:2px;vertical-align:middle;font-size:110%;">');
 table.insert(html_out_t,_infobox_ship_flag(args_t['Ship flag']));
 table.insert(html_out_t,'<span style="padding-left:1em">');
 table.insert(html_out_t,args_t['Ship country']);
 table.insert(html_out_t,'</span>');
 table.insert(html_out_t,'</th></tr>\n');
 elseifargs_t['Ship country']then
 table.insert(html_out_t,'<tr><th height="30" colspan="2" style="background-color:#B0C4DE;color:inherit;text-align:center;vertical-align:middle;font-size:110%;">');
 table.insert(html_out_t,args_t['Ship country']);
 table.insert(html_out_t,'</th></tr>\n');
 elseifargs_t['Ship flag']then
 table.insert(html_out_t,'<tr><th height="30" colspan="2" style="background-color:#B0C4DE;color:inherit;padding-left:2px;">');
 table.insert(html_out_t,_infobox_ship_flag(args_t['Ship flag']));
 table.insert(html_out_t,'</th></tr>\n');
 end
 end

 table.insert(html_out_t,line_items(args_t,data.infobox_career_params_t));-- add all of the rest of the template's html

 --mw.logObject (table.concat (html_out_t));
 returntable.concat(html_out_t);-- make a big string and done
 end


 --[[--------------------------< I N F O B O X _ S H I P _ C H A R A C T E R I S T I C S >----------------------

 implements {{Infobox ship characteristics}}

 {{#invoke:WPSHIPS utilities|infobox_ship_characteristics}}

 ]]

 localfunctioninfobox_ship_characteristics(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the template call

 localerr_cat=is_empty_ibox_template(args_t);-- look for and identify empty templates
 iferr_catthen
 returnerr_cat;-- template is empty so return the category and done
 end

 localhtml_out_t={};-- html table text goes here
 localerror_flag=false;-- controls emission of maint category when synonymous parameters are both set

 args_t['Hide header']=args_t['Hide header']andargs_t['Hide header']:lower();-- set to lowercase if set

 error_flag=synonym_check(args_t,'Ship armour','Ship armor',error_flag);-- error if both synonymous parameters set
 error_flag=synonym_check(args_t,'Ship draught','Ship draft',error_flag);

 if'yes'~=args_t['Hide header']then-- |Hide header=yes then no header
 table.insert(html_out_t,'<tr><th colspan="2" ');
 table.insert(html_out_t,styles.header_bar);-- style from WPMILHIST
 table.insert(html_out_t,'>General characteristics');
 ifargs_t['Header caption']then
 table.insert(html_out_t,' ');
 table.insert(html_out_t,args_t['Header caption']);
 end
 table.insert(html_out_t,'</th></tr>\n');
 end

 table.insert(html_out_t,line_items(args_t,data.infobox_characteristics_params_t));-- add all of the rest of the template's html

 --mw.logObject (table.concat (html_out_t));
 returntable.concat(html_out_t);-- make a big string and done
 end


 --[[--------------------------< I N F O B O X _ S H I P _ C L A S S _ O V E R V I E W >------------------------

 implements {{Infobox ship class overview}}

 {{#invoke:WPSHIPS utilities|infobox_ship_class_overview}}

 ]]

 localfunctioninfobox_ship_class_overview(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the template call

 localerr_cat=is_empty_ibox_template(args_t);-- look for and identify empty templates
 iferr_catthen
 returnerr_cat;-- template is empty so return the category and done
 end

 localhtml_out_t={};-- html table text goes here

 args_t['Hide header']=args_t['Hide header']andargs_t['Hide header']:lower();

 if'yes'~=args_t['Hide header']then-- |Hide header=yes then no header
 table.insert(html_out_t,'<tr><th colspan="2" ');
 table.insert(html_out_t,styles.header_bar);-- style from WPMILHIST
 table.insert(html_out_t,'>Class overview</th></tr>\n');
 end

 table.insert(html_out_t,line_items(args_t,data.infobox_class_overview_params_t));-- add all of the rest of the template's html

 --mw.logObject (table.concat (html_out_t));
 returntable.concat(html_out_t);-- make a big string and done
 end


 --[[--------------------------< I S _ P L I M S O L L _ F I L E N A M E >--------------------------------------

 validate cite plimsoll |filename=<filename>

 <filename> format is: YYvssss.pdf where
 	YY - least significant two digits of four-digit first year in a two-year range
 		30 -> 1930–1931
 		allowed values are all integers between and including 30–45
 	v - a single lowercase letter 'a' or 'b'
 		'a' -> volume I
 		'b' -> volume II
 	ssss - scan number begins with 0001
 		odd numbered scans have English headings
 		even numbered scans have French headings

 	{{#invoke:WPSHIPS utilities|is_plimsoll_filename|{{{filename}}}}}

 ]]

 localfunctionis_plimsoll_filename(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the invoke

 localyear,volume,scan;
 ifargs_t[1]then-- this to avoid script errors when args_t[1] missing
 year,volume,scan=args_t[1]:match('(%d%d)(%l)(%d%d%d%d)%.[Pp][Dd][Ff]');-- get the various parts
 end
 ifnotyearthenreturnnilend-- nil when no match so we're done
 year=tonumber(year);
 scan=tonumber(scan);
 if(30>year)or(45<year)thenreturnnilend
 ifnot(('a'==volume)or('b'==volume))thenreturnnilend
 if(1>scan)thenreturnnilend

 returntrue;
 end


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

 create two-year range from first two digits in |filename=<filename>
 	30 -> 1930–1931

 	{{#invoke:WPSHIPS utilities|set_plimsoll_date|{{{filename}}}}}

 ]]

 localfunctionset_plimsoll_date(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the invoke

 ifnotargs_t[1]then
 returnnil;
 end

 localyear=args_t[1]:match('(%d%d)%l%d%d%d%d');-- get the intial year

 year=1900+tonumber(year);-- make it a four-digit year
 returnstring.format('%d–%d',year,year+1);-- and then add one for the second year in the range
 end


 --[[--------------------------< S E T _ P L I M S O L L _ S U B T I T L E >-----------------------------------1

 used in {{cite plimsoll}}

 return appropriate subtitle string given |subtitle=<keyword>

 	{{#invoke:WPSHIPS utilities|set_plimsoll_subtitle|{{{subtitle}}}}}

 ]]

 localfunctionset_plimsoll_subtitle(frame)
 localsubtitle=get_args(frame)[1];-- get the subtitle parameter

 ifnotsubtitlethen
 returnnil;
 end

 ifnotdata.subtitles_t[subtitle]then
 return'&#58; '..subtitle;-- not predefined so return whatever |subtitle= holds with leading ': '
 end

 return'&#58; '..data.subtitles_t[subtitle];-- return predefined subtitle with leading ': '
 end


 --[[--------------------------< S E T _ P L I M S O L L _ U R L >----------------------------------------------

 create plimsoll url from |filename=<filename>

 	{{#invoke:WPSHIPS utilities|set_plimsoll_url|{{{filename}}}}}

 ]]

 localfunctionset_plimsoll_url(frame)
 localargs_t=get_args(frame);-- get a table of all parameters in the invoke

 ifargs_t[1]then
 returnstring.format('https://plimsoll.southampton.gov.uk/shipdata/pdfs/%s/%s',
 args_t[1]:match('(%d%d)%l%d%d%d%d'),-- get the year path portion from <filename>
 args_t[1]);-- append <filename> onto the end, and done
 end
 end


 --[[--------------------------< S C L A S S >------------------------------------------------------------------

 implements {{sclass}} and {{sclass2}}

 {{#invoke:WPSHIPS utilities|sclass}}

 ]]

 localfunctionsclass(frame)
 localargs_t=get_args(frame);
 localparent=frame:getParent();
 localtemplate=parent:getTitle():gsub('^Template:',''):lower();-- get the name of the template that called this module (includes namespace so strip that)

 localclass_name=args_t[1];-- names to make it easier to understand
 localship_type=args_t[2];
 localformat=args_t[3];
 localship_type_dab=args_t[4];
 localclass_name_dab=args_t[5];
 localno_cat='yes'==args_t['no-cat'];-- make a boolean

 ifnotclass_namethen-- when omitted, abandon with error message
 returnerror_msg_make('missing',template,'class name',no_cat);
 end

 ifnotship_typethen-- when omitted, abandon with error message
 returnerror_msg_make('missing',template,'ship type',no_cat);
 end

 ifformatthen
 iftonumber(format)then-- if <format> has a value that is a number
 format=tonumber(format);-- make it a number for comparisons
 if5<formatthen-- is <format> outside of allowed range
 returnerror_msg_make('format',template,format,no_cat);
 end
 else-- <format> could not be converted to a number
 returnerror_msg_make('format',template,format,no_cat);
 end
 end

 localout_t={};-- output goes here
 table.insert(out_t,'[[');-- open the wikilink
 table.insert(out_t,class_name);-- build the wikilink to the class article
 table.insert(out_t,'-class ');
 table.insert(out_t,ship_type);-- add ship type
 ifclass_name_dabthen-- when class article is disambiguated
 table.insert(out_t,' (');-- add the disambiguator
 table.insert(out_t,class_name_dab);
 table.insert(out_t,')');
 end
 table.insert(out_t,'|');
 if'sclass'==template:gsub('/sandbox','')then-- strip '/sandbox' if present; class named for a member of the class
 table.insert(out_t,'\'\'');-- class name is italicized
 table.insert(out_t,class_name);
 table.insert(out_t,'\'\'');
 else
 table.insert(out_t,class_name);-- class name is a common attribute; plain text
 end

 ifnotformator(3==format)then-- when format is omitted, same as format #3
 table.insert(out_t,'-class]] [[');-- open ship-type wikilink
 ifship_type_dabthen-- when ship-type article is disambiguated
 table.insert(out_t,ship_type);-- add ship type
 table.insert(out_t,' (');-- and the disambiguator
 table.insert(out_t,ship_type_dab);
 table.insert(out_t,')|');-- dab is not displayed so insert a pipe and
 end
 table.insert(out_t,ship_type);-- add ship type
 table.insert(out_t,']]');-- close ship-type wikilink
 end

 if0==formatthen-- no separate ship-type wikilink
 table.insert(out_t,'-class]]');
 end

 if1==formatthen-- no separate ship-type wikilink
 table.insert(out_t,'-class ');
 table.insert(out_t,ship_type);
 table.insert(out_t,']]');
 end

 if2==formatthen-- ship-type is not wikilinked
 table.insert(out_t,'-class]] ');
 table.insert(out_t,ship_type);
 end

 if4==formatthen-- noun form; no ship type
 table.insert(out_t,' class]]');
 end

 if5==formatthen-- class name only; no '-class' annotation
 table.insert(out_t,']]');
 end

 returntable.concat(out_t);
 end


 --[[--------------------------< E X P O R T S >----------------------------------------------------------------
 ]]

 return{
 cite_danfs_title=cite_danfs_title,-- external entry points for templates and invokes
 hnsa=hnsa,
 infobox_ship_career=infobox_ship_career,
 infobox_ship_characteristics=infobox_ship_characteristics,
 infobox_ship_class_overview=infobox_ship_class_overview,
 infobox_ship_flag=infobox_ship_flag,
 is_plimsoll_filename=is_plimsoll_filename,
 navsource=navsource,
 sclass=sclass,
 set_plimsoll_subtitle=set_plimsoll_subtitle,
 set_plimsoll_date=set_plimsoll_date,
 set_plimsoll_url=set_plimsoll_url,
 ship=ship,-- experiment
 ship_prefix_templates=ship_prefix_templates,-- experiment
 ship_name_format=ship_name_format,
 unbulleted_list=unbulleted_list,

 _infobox_ship_flag=_infobox_ship_flag,-- external entry points from another module
 _ship_name_format=do_ship_name_format,
 _synonym_check=synonym_check,
 _unbulleted_list=_unbulleted_list,
 }

AltStyle によって変換されたページ (->オリジナル) /