lib/infoboxer/navigation/shortcuts.rb
# frozen_string_literal: true
module Infoboxer
module Navigation
# See {Shortcuts::Node Shortcuts::Node} for everything!
module Shortcuts
# `Shortcuts::Node` module provides some convenience methods for
# most used lookups. It's not a rocket science (as you can see
# from methods code), yet should make your code cleaner and
# more readable.
#
# **NB**: as usual, {Tree::Nodes} class have synonyms for all of
# those methods, so you can call them fearlessly on any results of
# node lookup.
#
module Node
# Returns all wikilinks inside current node.
#
# @param namespace from which namespace links do you want. It's
# `''` (main namespace only) by default, if you really want all
# wikilinks on the page, including categories, interwikies and
# stuff, use `wikilinks(nil)`
# @return {Tree::Nodes}
def wikilinks(namespace = '')
lookup(Tree::Wikilink, namespace: namespace)
end
# Returns all headings inside current node.
#
# @param level headings level to return.
# @return {Tree::Nodes}
def headings(level = nil)
lookup(Tree::Heading, level: level)
end
# Returns all paragraph-level nodes (list items, plain paragraphs,
# headings and so on) inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def paragraphs(*selectors, &block)
lookup(Tree::BaseParagraph, *selectors, &block)
end
# Returns all external links inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def external_links(*selectors, &block)
lookup(Tree::ExternalLink, *selectors, &block)
end
# Returns all images (media) inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def images(*selectors, &block)
lookup(Tree::Image, *selectors, &block)
end
# Returns all templates inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def templates(*selectors, &block)
lookup(Tree::Template, *selectors, &block)
end
# Returns all tables inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def tables(*selectors, &block)
lookup(Tree::Table, *selectors, &block)
end
# Returns all lists (ordered/unordered/definition) inside current node.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def lists(*selectors, &block)
lookup(Tree::List, *selectors, &block)
end
# Returns true, if current node is **inside** bold.
def bold?
parent?(Tree::Bold)
end
# Returns true, if current node is **inside** italic.
def italic?
parent?(Tree::Italic)
end
# Returns true, if current node is **inside** heading.
#
# @param level optional concrete level to check
def heading?(level = nil)
parent?(Tree::Heading, level: level)
end
# Returns all infoboxes inside current node.
#
# Definition of what considered to be infobox depends on templates
# set used when parsing the page.
#
# @param selectors node selectors, as described at {Lookup::Node}
# @return {Tree::Nodes}
def infoboxes(*selectors, &block)
lookup(Tree::Template, :infobox?, *selectors, &block)
end
# Returns all wikilinks in "categories namespace".
#
# **NB**: depending on your MediaWiki settings, name of categories
# namespace may vary. When you are using {MediaWiki#get}, Infoboxer
# tries to handle this transparently (by examining used wiki for
# category names), yet bad things may happen here.
#
# @return {Tree::Nodes}
def categories
lookup(Tree::Wikilink, namespace: /^#{ensure_traits.category_namespace.join('|')}$/)
end
# As users accustomed to have only one infobox on a page
def infobox
infoboxes.first
end
private
def ensure_traits
ensure_page.traits or fail('No site traits found')
end
def ensure_page
(is_a?(MediaWiki::Page) ? self : lookup_parents(MediaWiki::Page).first) or
fail('Node is not inside Page, maybe parsed from text?')
end
end
# Companion module of {Shortcuts::Node Shortcuts::Node}, defining
# all the same methods for {Tree::Nodes} so you can use them
# uniformely on single node or list. See {Shortcuts::Node there} for
# details.
module Nodes
# @!method wikilinks(namespace = '')
# @!method headings(level = nil)
# @!method paragraphs(*selectors, &block)
# @!method external_links(*selectors, &block)
# @!method images(*selectors, &block)
# @!method templates(*selectors, &block)
# @!method tables(*selectors, &block)
# @!method lists(*selectors, &block)
# @!method infoboxes(*selectors, &block)
# @!method categories
%i[wikilinks headings paragraphs external_links images
templates tables lists infoboxes infobox categories]
.each do |m|
define_method(m) do |*args|
make_nodes(map { |n| n.send(m, *args) })
end
end
end
end
end
end