class Paru::Selector
A Selector
models a relationship between Pandoc
AST nodes, such as parent-child or sibling. Selectors in paru are like CSS selectors, but more limited because the Pandoc
AST is quite simple.
Given a selector expression, Selector
determines if a node complies with that selector expression or not.
Constants
- ANY_SELECTOR
Pseudo selector to select any inline and block node
- CLASS
Improved CSS class selector taken from stackoverflow.com/questions/448981/which-characters-are-valid-in-css-class-names-selectors/449000#449000
- DISTANCE
- OPERATOR
- OTHER_TYPE
- PSEUDO_SELECTORS
All pseudo selectors
- RELATION
- RELATIONS
- S
- SELECTOR
- TYPE
Public Class Methods
Create a new Selector
based on the selector string
@param selector [String] the selector string
# File lib/paru/selector.rb, line 44 def initialize(selector) @type = 'Unknown' @relations = [] parse selector end
Public Instance Methods
Does node get selected by this Selector
in the context of the already filtered nodes?
@param node [Node] the node to check against this Selector
@param filtered_nodes [Array<Node>] the context of filtered nodes to take
into account as well
@return [Boolean] True if the node in the context of the
filtered_nodes is selected by this Selector
# File lib/paru/selector.rb, line 59 def matches? node, filtered_nodes case @type when ANY_SELECTOR Paru::PANDOC_TYPES.include? node.type else node.type == @type and @classes.all? {|c| node.has_class? c } and @relations.all? {|r| r.matches? node, filtered_nodes} end end
Private Instance Methods
# File lib/paru/selector.rb, line 139 def continue_parsing?(parts) not parts.nil? and not parts[:relations].nil? end
# File lib/paru/selector.rb, line 104 def expect(parts, part) raise SelectorParseError.new "Expected #{part}" if parts[part].nil? parts[part] end
# File lib/paru/selector.rb, line 129 def expect_integer(parts, part) if parts[part].nil? number = 0 else number = parts[part].to_i raise SelectorParseError.new "Expected a positive #{part}, got '#{parts[part]}' instead" if number <= 0 end number end
# File lib/paru/selector.rb, line 109 def expect_match(regexp, string) match = regexp.match string raise SelectorParseError.new "Unable to parse '#{string}'" if match.nil? match end
# File lib/paru/selector.rb, line 122 def expect_pandoc_other_type(parts) type = expect parts, :other_name classes = parts[:other_classes].split('.').select {|c| not c.empty?} if not parts[:other_classes].nil? raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type [type, classes] end
# File lib/paru/selector.rb, line 115 def expect_pandoc_type(parts) type = expect parts, :name classes = parts[:classes].split(".").select {|c| not c.empty?} if not parts[:classes].nil? raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type [type, classes] end
Is type actually a Pandoc
AST node type?
# File lib/paru/selector.rb, line 100 def is_pandoc_type(type) Paru::PANDOC_TYPES.concat(PSEUDO_SELECTORS).include? type end
Parse the selector_string to construct this Selector
# File lib/paru/selector.rb, line 84 def parse(selector_string) partial_match = expect_match SELECTOR, selector_string @type, @classes = expect_pandoc_type partial_match while continue_parsing? partial_match operator = expect partial_match, :operator distance = expect_integer partial_match, :distance type, classes = expect_pandoc_other_type partial_match @relations.push Relation.new(operator, distance, type, classes) partial_match = rest partial_match end end
# File lib/paru/selector.rb, line 143 def rest(parts) rest_string = parts[:relations].slice 0, parts[:relations].size - parts[:relation].size RELATIONS.match rest_string end