Module:Page

From Pittsburgh Streets

This module implements the {{page}} template. The documentation for that template is transcluded below.

The {{page}} template formats a page number or range. For a single page, the abbreviation p. will be used; for a range (detected by the presence of a comma or en dash), the abbreviation pp. will be used. These can be modified with the descriptor and descriptor-plural parameters (for example, for an atlas that has numbered plates instead of pages).

An en dash can be entered as a literal en dash (), the HTML character entity –, or two hyphens (--).

The page number or range can be surrounded by square brackets ([...]) to indicate that the cited pages are not actually numbered (so the page numbers have been inferred from surrounding pages or by counting pages from the beginning of the work). In this case, {{page}} will insert the p. or pp. inside the brackets.

A page number can be followed by - or + to indicate that the actual page or page range cited precedes or follows the given page number, respectively. If this must be combined with square brackets, put the - or + sign inside the brackets (but try to avoid this—it doesn't quite make sense).

Some books have independently numbered parts (e.g., Source:History-of-allegheny-county has a part I with pages numbered 1–758, followed by a part II with pages numbered 1–790). To unambiguously refer to a page in such a book, it is necessary to name the part too. Specify the part before the page number, separated by a colon. For parts numbered by Roman numerals (I, II, III, . . .), give just the numeral, and part will be added automatically. For other kinds of parts (e.g., an appendix), part will not be added. See the usage examples below.

A literal string can be specified inside quotation marks ('...' or "..."), in which case {{page}} will directly return that string. This is useful when {{page}} is not being called directly but as part of another template. For example:

{{references
 |hopkins-1890-allegheny-vol-2@'plate 2'
}}

Usage examples

  • {{page|5}} → p. 5
  • {{page|iii}} → p. iii
  • {{page|395–449}} → pp. 395–449
  • {{page|7–19}} → pp. 7–19
  • {{page|30--37}} → pp. 30–37
  • {{page|vii–xxxvii}} → pp. vii–xxxvii
  • {{page|1, 9}} → pp. 1, 9
  • {{page|A-11}} → p. A-11
  • {{page|A-1, A-6}} → pp. A-1, A-6
  • {{page|C-1 – C-3}} → pp. C-1 – C-3
  • {{page|[23]}} → [p. 23]
  • {{page|[107–113]}} → [pp. 107–113]
  • {{page|iii-}} → preceding p. iii
  • {{page|200+}} → following p. 200
  • {{page|[132+]}} → following [p. 132]
  • {{page|II:97}} → part II, p. 97
  • {{page|I:487–488}} → part I, pp. 487–488
  • {{page|appendix:312–328}} → appendix, pp. 312–328
  • {{page|I:[347]}} → part I, [p. 347]
  • {{page|IV:25+}} → part IV, following p. 25
  • {{page|'plate 2'}} → plate 2
  • {{page|"inside front cover"}} → inside front cover
  • {{page|9|descriptor=plate}} → plate 9
  • {{page|25|descriptor=plate|descriptor-plural=plates}} → plate 25
  • {{page|12, 17|descriptor-plural=plates}} → plates 12, 17
  • {{page|9–10|descriptor=plate|descriptor-plural=plates}} → plates 9–10
  • {{page|2, 5|descriptor=ch.}} → ch. 2, 5
  • {{page|53|descriptor=|descriptor-plural=}} → p. 53
  • {{page|69, 73|descriptor=|descriptor-plural=}} → pp. 69, 73
  • {{page}}

local p = {};

function p.page(frame)
  local pg = frame:getParent().args[1];
  if not pg then
    return '';
  end

  if pg:len() >= 2 and (
      (pg:sub(1, 1) == "'" and pg:sub(-1) == "'") or
      (pg:sub(1, 1) == '"' and pg:sub(-1) == '"')
     ) then
    return pg:sub(2, -2);
  end

  local part = nil;
  local colon_pos = pg:find(':');
  if colon_pos then
    part = pg:sub(1, colon_pos - 1);
    if part:match('^[IVXLCDM]+$') then
      part = 'part ' .. part;
    end
    pg = pg:sub(colon_pos + 1);
  end

  local implied = false;
  if pg:sub(1, 1) == '[' and pg:sub(-1) == ']' then
    implied = true;
    pg = pg:sub(2, -2);
  end

  local prefix = '';
  if pg:sub(-1) == '+' then
    prefix = 'following ';
    pg = pg:sub(1, -2);
  elseif pg:sub(-1) == '-' then
    prefix = 'preceding ';
    pg = pg:sub(1, -2);
  end

  if pg == '' then
    return '';
  end

  pg = pg:gsub('%-%-', '–'):gsub('–', '–');

  local function nil_if_empty(s)
    if s == '' then
      return nil;
    end
    return s;
  end

  local descriptor = nil_if_empty(frame:getParent().args['descriptor']) or 'p.';
  local descriptor_plural =
    nil_if_empty(frame:getParent().args['descriptor-plural'])
    or nil_if_empty(frame:getParent().args['descriptor'])
    or 'pp.';

  local result = '';
  if part then
    result = part .. ', ';
  end
  result = result .. prefix;
  if implied then
    result = result .. '[';
  end
  if pg:find(',') or pg:find('–') then
    result = result .. descriptor_plural .. ' ';
  else
    result = result .. descriptor .. ' ';
  end
  result = result .. pg;
  if implied then
    result = result .. ']';
  end
  return result;
end

return p;