Module: RecipeScrapers::Sources::IngredientGroups

Defined in:
lib/recipe_scrapers/sources/ingredient_groups.rb

Constant Summary collapse

LAYOUTS =
[
  { heading: ".wprm-recipe-ingredient-group-name",
    item: ".wprm-recipe-ingredient" },
  { heading: ".tasty-recipes-ingredients p strong, .tasty-recipes-ingredients h4",
    item: ".tasty-recipes-ingredients li" },
  { heading: ".mv-create-ingredients h4, .mv-create-ingredients h3:not(.mv-create-ingredients-title)",
    item: ".mv-create-ingredients li" }
].freeze
SEPARATOR =
/\A[^\p{L}\p{N}]*\z/
HEADING =
/\A(?<purpose>\D+?)\s*:\z/

Class Method Summary collapse

Class Method Details

.call(document:, ingredients:, heading:, item:) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/recipe_scrapers/sources/ingredient_groups.rb', line 41

def call(document:, ingredients:, heading:, item:)
  return [ungrouped(ingredients)] if item.nil?

  headings = document.css(heading)
  return [ungrouped(ingredients)] if headings.empty?
  return [ungrouped(ingredients)] unless document.css(item).size == ingredients.size

  build(document.css("#{heading}, #{item}"), headings.to_a, ingredients)
end

.detect(document:, ingredients:) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/recipe_scrapers/sources/ingredient_groups.rb', line 33

def detect(document:, ingredients:)
  named = LAYOUTS.lazy.
          map { |layout| call(document: document, ingredients: ingredients, **layout) }.
          find { |groups| groups.any?(&:purpose) }

  named || [ungrouped(ingredients)]
end

.from_sections(sections) ⇒ Object



29
30
31
# File 'lib/recipe_scrapers/sources/ingredient_groups.rb', line 29

def from_sections(sections)
  sections.map { |purpose, lines| Models::IngredientGroup.new(purpose: purpose, ingredients: lines) }
end

.sections(lines, headings: []) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/recipe_scrapers/sources/ingredient_groups.rb', line 18

def sections(lines, headings: [])
  found = lines.grep_v(SEPARATOR).each_with_object([]) do |line, sections|
    purpose = headings.include?(line) ? line : line[HEADING, :purpose]
    next sections << [purpose, []] if purpose

    sections << [nil, []] if sections.empty?
    sections.last.last << line
  end
  found.reject { |_, section_lines| section_lines.empty? }
end