Module: ContentSpinning

Defined in:
lib/content_spinning.rb,
lib/content_spinning/version.rb

Defined Under Namespace

Modules: Version

Constant Summary collapse

SPIN_BEGIN_FOR_LEVEL =
Hash.new { |h, level| h[level] = "__SPIN_BEGIN_#{level}__" }
SPIN_END_FOR_LEVEL =
Hash.new { |h, level| h[level] = "__SPIN_END_#{level}__" }
SPIN_OR_FOR_LEVEL =
Hash.new { |h, level| h[level] = "__SPIN_OR_#{level}__" }
PARTITIONNER_REGEXP_FOR_LEVEL =
Hash.new do |h, level|
  h[level] = /#{SPIN_BEGIN_FOR_LEVEL[level]}.+?#{SPIN_END_FOR_LEVEL[level]}/
end
EMPTY_SPIN_REGEXP =
/\{\|*\}/
ONE_CHOICE_SPIN_REGEXP =
/\{([^\{\}\|]+)\}/
INNER_SPIN_REGEXP =
/\{([^\{\}]+)\}/

Class Method Summary collapse

Class Method Details

.clean(text) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/content_spinning.rb', line 33

def clean(text)
  cleaned = text.dup

  loop do
    text_before_run = cleaned.dup

    # Strip empty spin
    cleaned.gsub!(EMPTY_SPIN_REGEXP, "")

    # Remove spin with only one choice
    cleaned.gsub!(ONE_CHOICE_SPIN_REGEXP, '\1')

    break if cleaned == text_before_run
  end

  cleaned
end

.parse(text) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/content_spinning.rb', line 53

def parse(text)
  parsed = text.dup

  level = 0
  loop do
    level += 1

    modification_happened = parsed.gsub!(INNER_SPIN_REGEXP) do |match|
      match.sub!("{", SPIN_BEGIN_FOR_LEVEL[level])
      match.sub!("}", SPIN_END_FOR_LEVEL[level])
      match.gsub!("|", SPIN_OR_FOR_LEVEL[level])
    end

    break unless modification_happened
  end

  { parsed: parsed, max_level: level - 1 }
end

.spin(text) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/content_spinning.rb', line 15

def spin(text)
  result = parse(clean(text))

  contents = if result[:max_level] == 0
    [result[:parsed]]
  else
    spin_a_level([result[:parsed]], level: result[:max_level])
  end

  contents.reject!(&:empty?)
  contents.uniq!

  contents
end

.spin_a_level(contents, level:) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/content_spinning.rb', line 72

def spin_a_level(contents, level:)
  contents.flat_map do |text|
    parts = extract_parts(text, level: level)

    parts.map! do |part|
      spin_a_level(part, level: level - 1)
    end if level >= 2

    if parts.length > 1
      parts[0].product(*parts[1..-1]).tap do |products|
        products.map!(&:join)
      end
    else
      parts[0]
    end
  end
end