class MediaWiki::Page::ReplaceableContent

Constants

NAMED_TEMPLATE_PARAM_RE
TemplateNotFoundError

Attributes

client[RW]
template[RW]
title[RW]

Public Class Methods

new(client:, title:, template:) click to toggle source
# File lib/mediawiki/page.rb, line 12
def initialize(client:, title:, template:)
  @client = client
  @title = title
  @template = template
end

Public Instance Methods

anonymous_params() click to toggle source
# File lib/mediawiki/page.rb, line 55
def anonymous_params
  # FIXME: untemplate these using the MediaWiki API before
  # returning them.
  all_parameters.map { |p| NAMED_TEMPLATE_PARAM_RE =~ p ? nil : p }.compact
end
existing_content() click to toggle source
# File lib/mediawiki/page.rb, line 18
def existing_content
  page_parts[:to_replace]
end
param_key_value_array(key, value) click to toggle source
# File lib/mediawiki/page.rb, line 32
def param_key_value_array(key, value)
  [
    if key.strip =~ /^\d+$/
      Integer(Regexp.last_match[0])
    else
      key.strip.to_sym
    end,
    value
  ]
end
params() click to toggle source
# File lib/mediawiki/page.rb, line 43
def params
  # Returns the named parameters from the template tag as a Hash
  # where the keys are symbolized versions of the parameter
  # names.
  # FIXME: untemplate these using the MediaWiki API before
  # returning them.
  all_parameters.map do |p|
    m = NAMED_TEMPLATE_PARAM_RE.match(p)
    param_key_value_array(*m.captures) if m
  end.compact.to_h
end
reassemble_page(new_content, run_comment = '') click to toggle source
# File lib/mediawiki/page.rb, line 22
def reassemble_page(new_content, run_comment = '')
  format("%<before>s{{%<template_name>s%<parameters>s}}\n%<new_content>s\n<!-- OUTPUT END %<run_comment>s -->%<keep>s",
         page_parts.merge(new_content: new_content, run_comment: run_comment))
end
replace_output(new_content, run_comment = '') click to toggle source
# File lib/mediawiki/page.rb, line 27
def replace_output(new_content, run_comment = '')
  new_wikitext = reassemble_page(new_content, run_comment)
  client.edit(title: title, text: new_wikitext)
end

Private Instance Methods

all_parameters() click to toggle source
# File lib/mediawiki/page.rb, line 106
def all_parameters
  # This returns all parameters, including anonymous, numbered and
  # named parameters. (Though we only handle named parameters at
  # the moment.)
  page_parts[:parameters].split('|').select do |s|
    s.strip!
    s.empty? ? nil : s
  end
end
matchdata_to_h(matchdata) click to toggle source
# File lib/mediawiki/page.rb, line 116
def matchdata_to_h(matchdata)
  matchdata.names.map(&:to_sym).zip(matchdata.captures).to_h
end
page_parts() click to toggle source
# File lib/mediawiki/page.rb, line 84
def page_parts
  return @page_parts if @page_parts

  m = template_re.match(wikitext)
  raise TemplateNotFoundError, "The template '#{template}' was not found in '#{title}'" unless m

  parts = matchdata_to_h(m)
  @page_parts = parts.merge(split_after(parts[:after]))
end
split_after(after) click to toggle source
# File lib/mediawiki/page.rb, line 94
def split_after(after)
  # The part of the page after the template may or may not have
  # the special HTML comment that marks the end of the previous
  # output; if it's not there we insert the new content right
  # after the template tag.
  if after =~ /^(?<to_replace>.*?)\n<!-- OUTPUT END (?:.*?)-->(?<keep>.*)/m
    matchdata_to_h(Regexp.last_match)
  else
    { to_replace: '', keep: after }
  end
end
template_re() click to toggle source
# File lib/mediawiki/page.rb, line 69
def template_re
  # FIXME: there are obviously better ways of doing this parsing
  # than with a regular expression. e.g. there is an EBNF
  # version of the MediaWiki grammar which we could use to
  # generate a proper parser.
  /
    ^(?<before>.*?)
    \{\{
    (?<template_name>#{Regexp.quote(template)})
    (?<parameters>.*?)
    \}\}
    (?<after>.*)$
  /xm
end
wikitext() click to toggle source
# File lib/mediawiki/page.rb, line 65
def wikitext
  @wikitext ||= client.get_wikitext(title).body.dup.force_encoding('UTF-8')
end